zhhyu7 opened a new pull request, #19801: URL: https://github.com/apache/nuttx/pull/19801
## Summary In udp_input()'s broadcast/multicast fan-out loop, each iteration calls netdev_iob_replace(dev, iob) to swap in a freshly cloned iob before handing the packet to the next matching connection. That function unconditionally sets dev->d_len = iob->io_pktlen, which is the full frame length (IP + UDP headers + payload), undoing the 'dev->d_len -= udpiplen' done once before the loop to strip the headers off for udp_input_conn(). As a result, every connection after the first sees a d_len that is udpiplen (IP+UDP header length, eg 28 bytes for IPv4) too large. This value flows into udp_datahandler() as buflen (it reads dev->d_len directly) and is stored as the queued packet's declared length in the connection's read-ahead iob chain. Once more than one such oversized entry has queued up in the same chain, the consumer (udp_readahead() in udp_recvfrom.c) parses the following entry's metadata starting at the wrong offset, so whatever byte happens to land on src_addr_size is trusted as-is. That single byte (0-255) is then used as the length in iob_copyout(srcaddr, iob, src_addr_size, ...), which fills a fixed-size stack buffer with no bounds check outside a DEBUGASSERT - compiled out in release builds - so an oversized value overflows that stack buffer. Re-apply the same '-= udpiplen' header-stripping after each netdev_iob_replace() call in the loop, matching what's already done once before the loop for the first connection. Inside udp_input_conn, d_appdata is always set first, and since neither the ICMP nor ICMPv6 process accesses d_appdata, the redundant d_appdata settings have been removed. ## Impact Affects any target with CONFIG_NET_SOCKOPTS + CONFIG_NET_BROADCAST where two or more SO_REUSEADDR UDP sockets are bound to the same port and receive broadcast/multicast traffic — a normal, non-adversarial configuration (the issue reporter hit it without any malicious input). Security-relevant: stack buffer overflow in the network receive path. ## Testing Test logs not included in this change ``` NuttShell (NSH) NuttX-12.7.2 MOTD: username=admin password=Administrator nsh> hello & hello [5:100] nsh> Two UDP sockets (3, 4) bound to 0.0.0.0:5000, waiting for data... [sock0] recv 11 bytes from 10.0.1.1:59245 : "message one" [sock1] recv 39 bytes from 10.0.1.1:59245 : "message one'" [sock0] recv 11 bytes from 10.0.1.1:35721 : "message two" [sock1] recv 11 bytes from 10.0.1.1:47475 : "message one" [sock0] recv 13 bytes from 10.0.1.1:53994 : "message three" [sock1] recv 39 bytes from 10.0.1.1:54705 : "message two)" [sock0] recv 11 bytes from 10.0.1.1:47475 : "message one" ``` Test logs included in this change ``` NuttShell (NSH) NuttX-12.7.2 MOTD: username=admin password=Administrator nsh> hello & hello [5:100] nsh> Two UDP sockets (3, 4) bound to 0.0.0.0:5000, waiting for data... [sock0] recv 11 bytes from 10.0.1.1:38535 : "message one" [sock1] recv 11 bytes from 10.0.1.1:38535 : "message one" [sock0] recv 11 bytes from 10.0.1.1:60397 : "message two" [sock1] recv 11 bytes from 10.0.1.1:60397 : "message two" [sock0] recv 13 bytes from 10.0.1.1:51377 : "message three" [sock1] recv 13 bytes from 10.0.1.1:51377 : "message three" [sock0] recv 11 bytes from 10.0.1.1:58636 : "message one" [sock1] recv 11 bytes from 10.0.1.1:58636 : "message one" [sock0] recv 11 bytes from 10.0.1.1:37456 : "message two" [sock1] recv 11 bytes from 10.0.1.1:37456 : "message two" [sock0] recv 13 bytes from 10.0.1.1:60332 : "message three" [sock1] recv 13 bytes from 10.0.1.1:60332 : "message three" ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
