aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2026-05-22 17:57:31 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2026-05-22 17:57:31 +0000
commit933893771344e1647eeda152016b938fdc30ccdc (patch)
treec46f5fbddd116d75678466021738297d1fe8bfb2
parentb94689d036c5f5bdc04d080ff7dd5d0e9df9b8d4 (diff)
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
-rw-r--r--libexec/tftpd/tftp-io.c62
1 files 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);
}
/*