From: Drew Kluemke <[email protected]> The TFTP OACK handler matches option names in the received packet with strcasecmp(), which scans until a NUL byte. A malformed or truncated OACK packet may not contain a NUL within the received length, causing an out-of-bounds read past the packet buffer.
Replace each strcasecmp() with a strncasecmp() bounded to the option name length plus an explicit check that the name is NUL-terminated at the expected position. For the "windowsize" option, whose name and value extend beyond the loop's "i + 8 < len" guard, add an explicit "i + 11 < len" bound before the comparison. Signed-off-by: Drew Kluemke <[email protected]> Signed-off-by: Sriram Sriram <[email protected]> --- net/tftp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index beb9d08f5a2..35693e2a93e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -544,7 +544,8 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, * something like "len-8" may give a *huge* number */ for (i = 0; i+8 < len; i++) { - if (strcasecmp((char *)pkt + i, "blksize") == 0) { + if (!strncasecmp((char *)pkt + i, "blksize", 7) && + pkt[i + 7] == '\0') { tftp_block_size = (unsigned short) dectoul((char *)pkt + i + 8, NULL); debug("Blocksize oack: %s, %d\n", @@ -555,7 +556,8 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, tftp_state = STATE_INVALID_OPTION; } } - if (strcasecmp((char *)pkt + i, "timeout") == 0) { + if (!strncasecmp((char *)pkt + i, "timeout", 7) && + pkt[i + 7] == '\0') { timeout_val_rcvd = (unsigned short) dectoul((char *)pkt + i + 8, NULL); debug("Timeout oack: %s, %d\n", @@ -567,14 +569,17 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, } } #ifdef CONFIG_TFTP_TSIZE - if (strcasecmp((char *)pkt + i, "tsize") == 0) { + if (!strncasecmp((char *)pkt + i, "tsize", 5) && + pkt[i + 5] == '\0') { tftp_tsize = dectoul((char *)pkt + i + 6, NULL); debug("size = %s, %u\n", (char *)pkt + i + 6, tftp_tsize); } #endif - if (strcasecmp((char *)pkt + i, "windowsize") == 0) { + if (i + 11 < len && + !strncasecmp((char *)pkt + i, "windowsize", 10) && + pkt[i + 10] == '\0') { tftp_windowsize = dectoul((char *)pkt + i + 11, NULL); debug("windowsize = %s, %d\n", -- 2.49.0
