summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
author陈谋顺 <[email protected]>2026-10-09 11:16:57 +0800
committerRbb666 <[email protected]>2026-10-10 17:20:57 +0800
commit887ca7175cfef7f11f8566020d23335e9a73f271 (patch)
tree0fda17a87a261925543091a16c9aa6709438ece0 /components
parentcd92c3d06c880d097059ee3e0bf17cd54abb4603 (diff)
[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
Diffstat (limited to 'components')
-rw-r--r--components/net/lwip-dhcpd/dhcp_server.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/components/net/lwip-dhcpd/dhcp_server.c b/components/net/lwip-dhcpd/dhcp_server.c
index 0cc08b5a6e..9df685ebe5 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;