dhcp_message_type() scans DHCP options looking for a 0xff
end-of-options marker with no check that the scan pointer stays
within the received packet. A server can send a crafted OFFER with
no 0xff terminator and large option length fields, advancing the
pointer past bp_vend[312] into adjacent heap memory.

This is the same class of bug as CVE-2024-42040, which fixed the
related bootp_process_vendor() call site. Fix it by adding an end
parameter to dhcp_message_type() and checking that popt is lower
than end.

Signed-off-by: Francois Berder <[email protected]>
---
 net/bootp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/bootp.c b/net/bootp.c
index 8976936b184..f0dc329d6e4 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -997,13 +997,13 @@ static void dhcp_packet_process_options(struct bootp_hdr 
*bp)
        }
 }
 
-static int dhcp_message_type(unsigned char *popt)
+static int dhcp_message_type(unsigned char *popt, unsigned char *end)
 {
        if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC))
                return -1;
 
        popt += 4;
-       while (*popt != 0xff) {
+       while (popt < end && *popt != 0xff) {
                if (*popt == 53)        /* DHCP Message Type */
                        return *(popt + 2);
                if (*popt == 0) {
@@ -1120,7 +1120,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, 
struct in_addr sip,
                            strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
 #endif /* CONFIG_SYS_BOOTFILE_PREFIX */
                        if (CONFIG_IS_ENABLED(UNIT_TEST) &&
-                           dhcp_message_type((u8 *)bp->bp_vend) == -1) {
+                           dhcp_message_type((u8 *)bp->bp_vend, (u8 *)pkt + 
len) == -1) {
                                debug("got BOOTP response; transitioning to 
BOUND\n");
                                goto dhcp_got_bootp;
                        }
@@ -1149,7 +1149,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, 
struct in_addr sip,
        case REQUESTING:
                debug("DHCP State: REQUESTING\n");
 
-               if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
+               if (dhcp_message_type((u8 *)bp->bp_vend, (u8 *)pkt + len) == 
DHCP_ACK) {
 dhcp_got_bootp:
                        dhcp_packet_process_options(bp);
                        /* Store net params from reply */
-- 
2.43.0

Reply via email to