Skip to content

Stack buffer over-read in lpd_command() via vsnprintf return value misuse #1543

@Tomer-PL

Description

@Tomer-PL

Summary

In backend/lpd.c:646-657, vsnprintf returns the number of bytes that would have been written (C99), not the number actually written. When the formatted string exceeds sizeof(buf) (1024), lpd_write(fd, buf, (size_t)bytes) sends more bytes than the buffer contains, reading past the stack buffer and sending the extra bytes over the network to the LPD server.

Details

// backend/lpd.c:629,646,657
char buf[1024];
ssize_t bytes;

bytes = vsnprintf(buf, sizeof(buf), format, ap);  // Returns WOULD-HAVE-BEEN length
// If formatted string > 1024: bytes > sizeof(buf), but buf only has 1023 chars + NUL

if (lpd_write(fd, buf, (size_t)bytes) < bytes)  // Sends 'bytes' from 1024-byte buffer
    // Reads past buf[] into adjacent stack memory

Triggered at line 986: lpd_command(fd, "\002%s\n", printer) where printer comes from the URI resource path. A printer name of ~1022+ characters causes the formatted string to exceed the buffer.

Reproducer

Configure an LPD printer with a long queue name:

lpadmin -p longname -v "lpd://server/$(python3 -c 'print("A"*1100)')" -E

When a job is submitted, lpd_command formats \002AAAA...1100 A's...\n into the 1024-byte buffer. vsnprintf returns 1103 but only writes 1023 bytes. lpd_write sends 1103 bytes from the 1024-byte buffer — 79 bytes of stack memory leaked to the LPD server.

ASan output:

ERROR: AddressSanitizer: stack-buffer-overflow
READ at offset 1152 past buf variable

Suggested Fix

  bytes = vsnprintf(buf, sizeof(buf), format, ap);
+ if (bytes >= (ssize_t)sizeof(buf))
+     bytes = (ssize_t)sizeof(buf) - 1;

Metadata

Metadata

Assignees

Labels

wontfixThis will not be worked on

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions