From 451f9efa79935f4177d7dfa7e00d4f17a89cceee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E8=B0=8B=E9=A1=BA?= Date: Fri, 9 Oct 2026 11:16:57 +0800 Subject: [PATCH 1/2] [components][lwip] dhcpd: check buffer bounds when parsing options The option loop advanced by the option length without checking the number of bytes actually received by recvfrom(), so a malformed or truncated DHCP packet could make the server read past the end of the receive buffer. Check that the option type, length and payload stay inside the received data before reading them, and stop parsing when a requested IP option is shorter than 4 bytes or a message type option is shorter than 1 byte. Fixes #11323 --- components/net/lwip-dhcpd/dhcp_server.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/components/net/lwip-dhcpd/dhcp_server.c b/components/net/lwip-dhcpd/dhcp_server.c index 0cc08b5a6e57..9df685ebe50f 100644 --- a/components/net/lwip-dhcpd/dhcp_server.c +++ b/components/net/lwip-dhcpd/dhcp_server.c @@ -331,6 +331,7 @@ static void dhcpd_thread_entry(void *parameter) /* handler. */ { uint8_t *dhcp_opt; + uint8_t *dhcp_opt_end; uint8_t option; uint8_t length; @@ -343,14 +344,31 @@ static void dhcpd_thread_entry(void *parameter) client_ip_3 = get_ip(&mac_addr); dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; + dhcp_opt_end = (uint8_t *)msg + bytes_read; while (finished == 0) { + /* need at least option + length */ + if (dhcp_opt + 2 > dhcp_opt_end) + { + break; + } + option = *dhcp_opt; length = *(dhcp_opt + 1); + /* option data must stay within the received packet */ + if (option != DHCP_OPTION_END && dhcp_opt + 2 + length > dhcp_opt_end) + { + break; + } + switch (option) { case DHCP_OPTION_REQUESTED_IP: + if (length < 4) + { + break; + } request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16 | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5); break; @@ -360,6 +378,10 @@ static void dhcpd_thread_entry(void *parameter) break; case DHCP_OPTION_MESSAGE_TYPE: + if (length < 1) + { + break; + } message_type = *(dhcp_opt + 2); break; From 31ab059a71b9ece1fe77e3cd777215cdfc638081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E8=B0=8B=E9=A1=BA?= Date: Fri, 9 Oct 2026 11:17:11 +0800 Subject: [PATCH 2/2] [components][lwip] dhcpd: apply clang-format to dhcp_server.c --- components/net/lwip-dhcpd/dhcp_server.c | 74 ++++++++++++++----------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/components/net/lwip-dhcpd/dhcp_server.c b/components/net/lwip-dhcpd/dhcp_server.c index 9df685ebe50f..6b4e80461d44 100644 --- a/components/net/lwip-dhcpd/dhcp_server.c +++ b/components/net/lwip-dhcpd/dhcp_server.c @@ -49,62 +49,64 @@ #include #if (LWIP_VERSION) >= 0x02000000U - #include +#include #endif /* DHCP server option */ /* allocated client ip range */ #ifndef DHCPD_CLIENT_IP_MIN - #define DHCPD_CLIENT_IP_MIN 2 +#define DHCPD_CLIENT_IP_MIN 2 #endif #ifndef DHCPD_CLIENT_IP_MAX - #define DHCPD_CLIENT_IP_MAX 254 +#define DHCPD_CLIENT_IP_MAX 254 #endif /* the DHCP server address */ #ifndef DHCPD_SERVER_IP - #define DHCPD_SERVER_IP "192.168.169.1" +#define DHCPD_SERVER_IP "192.168.169.1" #endif //#define DHCP_DEBUG_PRINTF -#ifdef DHCP_DEBUG_PRINTF - #define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf +#ifdef DHCP_DEBUG_PRINTF +#define DEBUG_PRINTF \ + rt_kprintf("[DHCP] "); \ + rt_kprintf #else - #define DEBUG_PRINTF(...) +#define DEBUG_PRINTF(...) #endif /* DHCP_DEBUG_PRINTF */ /* we need some routines in the DHCP of lwIP */ -#undef LWIP_DHCP -#define LWIP_DHCP 1 +#undef LWIP_DHCP +#define LWIP_DHCP 1 #include #ifndef DHCP_CLIENT_PORT -#define DHCP_CLIENT_PORT 68 +#define DHCP_CLIENT_PORT 68 #endif #ifndef DHCP_SERVER_PORT -#define DHCP_SERVER_PORT 67 +#define DHCP_SERVER_PORT 67 #endif #ifndef ETHADDR32_COPY -#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) #endif #ifndef ETHADDR16_COPY -#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) #endif /* buffer size for receive DHCP packet */ -#define BUFSZ 1024 +#define BUFSZ 1024 #ifndef MAC_ADDR_LEN - #define MAC_ADDR_LEN 6 +#define MAC_ADDR_LEN 6 #endif #ifndef MAC_TABLE_LEN - #define MAC_TABLE_LEN 4 +#define MAC_TABLE_LEN 4 #endif struct mac_addr_t @@ -128,20 +130,22 @@ static rt_err_t _low_level_dhcp_send(struct netif *netif, struct udp_hdr *udphdr; p = pbuf_alloc(PBUF_LINK, - SIZEOF_ETH_HDR + sizeof(struct ip_hdr) - + sizeof(struct udp_hdr) + size, + SIZEOF_ETH_HDR + sizeof(struct ip_hdr) + sizeof(struct udp_hdr) + size, PBUF_RAM); - if (p == RT_NULL) return -RT_ENOMEM; + if (p == RT_NULL) + { + return -RT_ENOMEM; + } ethhdr = (struct eth_hdr *)p->payload; - iphdr = (struct ip_hdr *)((char *)ethhdr + SIZEOF_ETH_HDR); + iphdr = (struct ip_hdr *)((char *)ethhdr + SIZEOF_ETH_HDR); udphdr = (struct udp_hdr *)((char *)iphdr + sizeof(struct ip_hdr)); ETHADDR32_COPY(ðhdr->dest, (struct eth_addr *)ðbroadcast); ETHADDR16_COPY(ðhdr->src, netif->hwaddr); ethhdr->type = PP_HTONS(ETHTYPE_IP); - iphdr->src.addr = 0x00000000; /* src: 0.0.0.0 */ + iphdr->src.addr = 0x00000000; /* src: 0.0.0.0 */ iphdr->dest.addr = 0xFFFFFFFF; /* src: 255.255.255.255 */ IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); @@ -207,16 +211,20 @@ static uint8_t get_ip(struct mac_addr_t *p_mac_addr) /* add new ip */ mac_table[offset].mac_addr = *p_mac_addr; - mac_table[offset].ip_addr_3 = next_client_ip; - ip_addr_3 = mac_table[offset].ip_addr_3 ; + mac_table[offset].ip_addr_3 = next_client_ip; + ip_addr_3 = mac_table[offset].ip_addr_3; offset++; if (offset >= MAC_TABLE_LEN) + { offset = 0; + } next_client_ip++; if (next_client_ip > DHCPD_CLIENT_IP_MAX) + { next_client_ip = DHCPD_CLIENT_IP_MIN; + } DEBUG_PRINTF("create new ip: %d\n", (int)ip_addr_3); DEBUG_PRINTF("next_client_ip %d\n", next_client_ip); @@ -239,7 +247,7 @@ static void dhcpd_thread_entry(void *parameter) uint8_t DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, DHCPD_SERVER_IPADDR2, DHCPD_SERVER_IPADDR3; /* get ethernet interface. */ - netif = (struct netif *) parameter; + netif = (struct netif *)parameter; RT_ASSERT(netif != RT_NULL); /* our DHCP server information */ @@ -254,8 +262,8 @@ static void dhcpd_thread_entry(void *parameter) DHCPD_SERVER_IPADDR0 = (ntohl(addr.addr) >> 24) & 0xFF; DHCPD_SERVER_IPADDR1 = (ntohl(addr.addr) >> 16) & 0xFF; - DHCPD_SERVER_IPADDR2 = (ntohl(addr.addr) >> 8) & 0xFF; - DHCPD_SERVER_IPADDR3 = (ntohl(addr.addr) >> 0) & 0xFF; + DHCPD_SERVER_IPADDR2 = (ntohl(addr.addr) >> 8) & 0xFF; + DHCPD_SERVER_IPADDR3 = (ntohl(addr.addr) >> 0) & 0xFF; } DEBUG_PRINTF("DHCP server IP: %d.%d.%d.%d client IP: %d.%d.%d.%d-%d\n", DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, @@ -337,7 +345,7 @@ static void dhcpd_thread_entry(void *parameter) uint8_t message_type = 0; uint8_t finished = 0; - uint32_t request_ip = 0; + uint32_t request_ip = 0; uint8_t client_ip_3; @@ -369,8 +377,7 @@ static void dhcpd_thread_entry(void *parameter) { break; } - request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16 - | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5); + request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16 | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5); break; case DHCP_OPTION_END: @@ -398,8 +405,7 @@ static void dhcpd_thread_entry(void *parameter) /* check. */ if (request_ip) { - uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16 - | DHCPD_SERVER_IPADDR2 << 8 | client_ip_3; + uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16 | DHCPD_SERVER_IPADDR2 << 8 | client_ip_3; DEBUG_PRINTF("message_type: %d, request_ip: %08X, client_ip: %08X.\n", message_type, request_ip, client_ip); @@ -505,8 +511,8 @@ static void dhcpd_thread_entry(void *parameter) *dhcp_opt++ = (ntohl(dns_addr.addr) >> 24) & 0xFF; *dhcp_opt++ = (ntohl(dns_addr.addr) >> 16) & 0xFF; - *dhcp_opt++ = (ntohl(dns_addr.addr) >> 8) & 0xFF; - *dhcp_opt++ = (ntohl(dns_addr.addr) >> 0) & 0xFF; + *dhcp_opt++ = (ntohl(dns_addr.addr) >> 8) & 0xFF; + *dhcp_opt++ = (ntohl(dns_addr.addr) >> 0) & 0xFF; } #endif @@ -560,7 +566,9 @@ void dhcpd_start(const char *netif_name) while (netif != RT_NULL) { if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) + { break; + } netif = netif->next; if (netif == RT_NULL)