K-ANOY opened a new issue, #3950:
URL: https://github.com/apache/nuttx-apps/issues/3950

   ### Description / Steps to reproduce the issue
   
   i8shark puts the radio into promiscuous mode and reads received 802.15.4 
frames from the MAC
   character driver, then copies the frame payload into a fixed stack buffer 
sized to the exact
   theoretical maximum (zero margin), using the device-reported 
`frame.length`/`frame.offset`
   without any validation.
   
   `wireless/ieee802154/i8shark/i8shark_main.c`, `i8shark_main()` RX loop:
   
   ```c
   179   ieee802154_setpromisc(fd, true);                 /* promiscuous: no 
length clamp in driver */
   ...
   235   ret = read(fd, &frame, sizeof(struct mac802154dev_rxframe_s));
   ...
   77  #define ZEP_MAX_HDRSIZE         32
   78  #define I8SHARK_MAX_ZEPFRAME    (IEEE802154_MAX_PHY_PACKET_SIZE + 
ZEP_MAX_HDRSIZE)  /* 159 */
   228   uint8_t zepframe[I8SHARK_MAX_ZEPFRAME];          /* 159 bytes */
   ...
   363   memcpy(&zepframe[i], frame.payload, frame.length);   /* i == 32; SINK 
*/
   ```
   
   `frame.length` and `frame.offset` are filled by the kernel MAC driver 
straight from the received
   over-the-air frame (`rx->length = io_len + fcslen` on the promiscuous 
branch); neither the driver
   nor the app clamps `length` to `IEEE802154_MAX_PHY_PACKET_SIZE` (127). The 
ZEP header occupies
   the first 32 bytes, so the max written index is `32 + frame.length - 1`. A 
full PSDU plus FCS
   (`length = io_len + fcslen`, e.g. 127 + 2 = 129) gives index 160 → stack OOB 
write past
   `zepframe[158]`. No bound check (not even `DEBUGASSERT`) guards 
`frame.length`/`frame.offset`.
   
   Two additional, config-gated sink variants are worse:
   
   - XBEE app-header variant (`CONFIG_IEEE802154_I8SHARK_XBEE_APPHDR`): signed 
underflow —
   
   ```c
   347   memcpy(&zepframe[i], (frame.payload + frame.offset + 2),
                              (frame.length - frame.offset - 2));
   ```
     `frame.length - frame.offset - 2` is an `int`; a short/malformed frame with
     `offset + 2 > length` yields a negative value → huge `size_t` in `memcpy` 
→ massive OOB.
   
   - SUPPRESS_FCS variant (`CONFIG_IEEE802154_I8SHARK_SUPPRESS_FCS`): `uint8_t` 
underflow —
   
   ```c
   359   frame.length -= fcslen;      /* underflows to ~254 if length < fcslen 
*/
   ```
   
   Any device transmitting an 802.15.4 frame within radio range controls these 
bytes.
   
   Steps:
   1. Build and run the i8shark sniffer (`CONFIG_IEEE802154_I8SHARK`) on an 
802.15.4 radio.
   2. Transmit a crafted/maximal 802.15.4 frame within range (and, for the 
variants, a short frame
      with `offset + 2 > length`, or `length < fcslen`).
   3. The RX loop `memcpy` writes past `zepframe[158]` on the stack.
   
   An AddressSanitizer build reports a stack-buffer-overflow WRITE past the 
159-byte `zepframe`.
   
   **Expected:** a frame with `length > 127` or `offset > length` (or `offset + 
2 > length` in the
   XBEE path) is dropped.
   **Actual:** the `memcpy` writes past `zepframe[158]`, or computes a 
negative/underflowed size.
   
   **Suggested fix:** immediately after `read()`, validate `frame.length <= 
IEEE802154_MAX_PHY_PACKET_SIZE`,
   `frame.offset <= frame.length`, and (XBEE) `frame.length >= frame.offset + 
2`; drop the frame
   otherwise.
   
   ### On which OS does this issue occur?
   
   [OS: Linux]
   
   ### What is the version of your OS?
   
   ubuntu 22
   
   ### NuttX Version
   
   master
   
   ### Issue Architecture
   
   [Arch: all]
   
   ### Issue Area
   
   [Area: Wireless]
   
   ### Host information
   
   _No response_
   
   ### Verification
   
   - [x] I have verified before submitting the report.


-- 
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]

Reply via email to