git: 02f9207a8140 - stable/15 - lpd: Avoid buffer overflow when sending a job
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 28 May 2026 08:25:21 UTC
The branch stable/15 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=02f9207a81403d06b7d0cb52e141572ffeafb54a
commit 02f9207a81403d06b7d0cb52e141572ffeafb54a
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-05-25 16:51:48 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-05-28 08:24:16 +0000
lpd: Avoid buffer overflow when sending a job
When forwarding a print job to a remote server, we could overflow the
command buffer if a control or data file had a very long name.
MFC after: 1 week
Reported by: Joshua Rogers <joshua@joshua.hu>
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D57184
(cherry picked from commit f2c7c5f94803b67a9a6af625d4fc8882d2afda6c)
---
usr.sbin/lpr/lpd/printjob.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c
index 1c6736097492..0e86e8de8fb9 100644
--- a/usr.sbin/lpr/lpd/printjob.c
+++ b/usr.sbin/lpr/lpd/printjob.c
@@ -68,8 +68,12 @@
/*
* The buffer size to use when reading/writing spool files.
+ * This is also used to compose commands for remote servers and therefore
+ * needs to be able to fit the longest command we could possibly send.
*/
-#define SPL_BUFSIZ BUFSIZ
+#define SPL_BUFSIZ (BUFSIZ * 2)
+_Static_assert(SPL_BUFSIZ > sizeof("x18446744073709551615 ") + PATH_MAX +
+ sizeof("_c2147483647 "), "SPL_BUFSIZ is too short");
/*
* Error tokens
@@ -640,7 +644,7 @@ print(struct printer *pp, int format, char *file)
if (pp->filters[LPF_INPUT] == NULL
&& (format == 'f' || format == 'l' || format == 'o')) {
pp->tof = 0;
- while ((n = read(fi, buf, SPL_BUFSIZ)) > 0)
+ while ((n = read(fi, buf, sizeof(buf))) > 0)
if (write(ofd, buf, n) != n) {
(void) close(fi);
return (REPRINT);
@@ -1127,13 +1131,18 @@ sendfile(struct printer *pp, int type, char *file, char format, int copyreq)
sendagain:
copycnt++;
- if (copycnt < 2)
- (void) sprintf(buf, "%c%" PRId64 " %s\n", type, stb.st_size,
- file);
- else
- (void) sprintf(buf, "%c%" PRId64 " %s_c%d\n", type, stb.st_size,
- file, copycnt);
- amt = strlen(buf);
+ if (copycnt < 2) {
+ amt = snprintf(buf, sizeof(buf), "%c%" PRId64 " %s\n",
+ type, stb.st_size, file);
+ } else {
+ amt = snprintf(buf, sizeof(buf), "%c%" PRId64 " %s_c%d\n",
+ type, stb.st_size, file, copycnt);
+ }
+ if (amt >= sizeof(buf)) {
+ syslog(LOG_ERR, "%s: file name too long", file);
+ sfres = ERROR;
+ goto return_sfres;
+ }
for (i = 0; ; i++) {
if (write(pfd, buf, amt) != amt ||
(resp = response(pp)) < 0 || resp == '\1') {
@@ -1157,8 +1166,8 @@ sendagain:
*/
if (type == '\3')
trstat_init(pp, file, job_dfcnt);
- for (i = 0; i < stb.st_size; i += SPL_BUFSIZ) {
- amt = SPL_BUFSIZ;
+ for (i = 0; i < stb.st_size; i += sizeof(buf)) {
+ amt = sizeof(buf);
if (i + amt > stb.st_size)
amt = stb.st_size - i;
if (sizerr == 0 && read(sfd, buf, amt) != amt)