git: dd9272210d45 - stable/15 - tftpd: Add missing bounds checks
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 27 May 2026 09:03:34 UTC
The branch stable/15 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=dd9272210d456df3e2ce98e4c5696e15170edcf4
commit dd9272210d456df3e2ce98e4c5696e15170edcf4
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-05-22 17:57:31 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-05-27 09:03:21 +0000
tftpd: Add missing bounds checks
In send_[rw]rq(), we were using strlcpy() to avoid overflowing our
packet buffer, then failing to check the result and blithely advancing
our pointer by the full length.
Luckily, this code is only ever used by tftp(1), not tftpd(8).
MFC after: 1 week
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D57075
(cherry picked from commit 933893771344e1647eeda152016b938fdc30ccdc)
---
libexec/tftpd/tftp-io.c | 62 +++++++++++++++++++++++++++----------------------
1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/libexec/tftpd/tftp-io.c b/libexec/tftpd/tftp-io.c
index 50102e652d2f..3384071d6df2 100644
--- a/libexec/tftpd/tftp-io.c
+++ b/libexec/tftpd/tftp-io.c
@@ -173,11 +173,11 @@ send_error(int peer, int error)
int
send_wrq(int peer, char *filename, char *mode)
{
- int n;
+ char buf[MAXPKTSIZE];
struct tftphdr *tp;
char *bp;
- char buf[MAXPKTSIZE];
- int size;
+ size_t len;
+ int n, size;
if (debug & DEBUG_PACKETS)
tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'",
@@ -191,17 +191,17 @@ send_wrq(int peer, char *filename, char *mode)
size = offsetof(struct tftphdr, th_stuff);
bp = tp->th_stuff;
- strlcpy(bp, filename, sizeof(buf) - size);
- bp += strlen(filename);
- *bp = 0;
- bp++;
- size += strlen(filename) + 1;
-
- strlcpy(bp, mode, sizeof(buf) - size);
- bp += strlen(mode);
- *bp = 0;
- bp++;
- size += strlen(mode) + 1;
+ len = strlcpy(bp, filename, sizeof(buf) - size);
+ if (len >= sizeof(buf) - size)
+ goto overflow;
+ bp += len + 1;
+ size += len + 1;
+
+ len = strlcpy(bp, mode, sizeof(buf) - size);
+ if (len >= sizeof(buf) - size)
+ goto overflow;
+ bp += len + 1;
+ size += len + 1;
if (options_rfc_enabled)
size += make_options(peer, bp, sizeof(buf) - size);
@@ -213,6 +213,9 @@ send_wrq(int peer, char *filename, char *mode)
return (1);
}
return (0);
+overflow:
+ tftp_log(LOG_ERR, "%s: file name too long", __func__);
+ return (1);
}
/*
@@ -221,11 +224,11 @@ send_wrq(int peer, char *filename, char *mode)
int
send_rrq(int peer, char *filename, char *mode)
{
- int n;
+ char buf[MAXPKTSIZE];
struct tftphdr *tp;
char *bp;
- char buf[MAXPKTSIZE];
- int size;
+ size_t len;
+ int n, size;
if (debug & DEBUG_PACKETS)
tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'",
@@ -239,17 +242,17 @@ send_rrq(int peer, char *filename, char *mode)
size = offsetof(struct tftphdr, th_stuff);
bp = tp->th_stuff;
- strlcpy(bp, filename, sizeof(buf) - size);
- bp += strlen(filename);
- *bp = 0;
- bp++;
- size += strlen(filename) + 1;
-
- strlcpy(bp, mode, sizeof(buf) - size);
- bp += strlen(mode);
- *bp = 0;
- bp++;
- size += strlen(mode) + 1;
+ len = strlcpy(bp, filename, sizeof(buf) - size);
+ if (len >= sizeof(buf) - size)
+ goto overflow;
+ bp += len + 1;
+ size += len + 1;
+
+ len = strlcpy(bp, mode, sizeof(buf) - size);
+ if (len >= sizeof(buf) - size)
+ goto overflow;
+ bp += len + 1;
+ size += len + 1;
if (options_rfc_enabled) {
options_set_request(OPT_TSIZE, "0");
@@ -263,6 +266,9 @@ send_rrq(int peer, char *filename, char *mode)
return (1);
}
return (0);
+overflow:
+ tftp_log(LOG_ERR, "%s: file name too long", __func__);
+ return (1);
}
/*