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

   ### Description / Steps to reproduce the issue
   
   In `drivers/input/st7123.c` (ST7123 I2C touch controller) the 
device-reported `max_touches` value
   sizes a single I2C burst read into the fixed 74-byte frame buffer with no 
upper clamp — the promised
   clamp exists only in a comment, so the bound is **absent** in all build 
configurations. This is a
   heap out-of-bounds **write** (CWE-787) of up to 1715 bytes of 
attacker-controlled I2C data past the
   74-byte frame field, clobbering the rest of the device structure and 
adjacent heap (High severity).
   The attacker is a malicious/compromised ST7123 touch controller on the I2C 
bus.
   
   At probe, the driver reads the controller's capability block (including the 
`uint8_t`
   `max_touches` at register `0x09`) over I2C, then uses that value — with no 
upper clamp — to size
   a single I2C burst read into the fixed-size frame buffer on every touch 
interrupt:
   
   ```c
   /* drivers/input/st7123.c */
   830   st7123_read_sequential(dev, ST7123_TOUCH_MAX_X_COORD_H,
                                (uint8_t *) &dev->device_caps, 
sizeof(dev->device_caps));
   ...
   955   if (priv->device_caps.max_touches == 0)   /* only guard: reject zero */
           { ... return -ENODEV; }
   962   priv->lower.maxpoint = priv->device_caps.max_touches;   /* up to 255, 
no upper clamp */
   ...
   645   framelen = ST7123_FRAME_HEADER_SIZE +            /* 4 */
                  lower->maxpoint * ST7123_TOUCH_AREA_SIZE;   /* maxpoint * 7 */
   648   st7123_read_sequential(dev, ST7123_TOUCH_ADV_TOUCH_INFO,
                                (uint8_t *) &dev->frame, framelen);   /* SINK */
   ```
   
   `st7123_read_sequential()` → `i2c_writeread(dev->i2c, ..., value, count)` 
(`:571`) reads
   `framelen` device bytes straight into `dev->frame`.
   
   The destination `struct st7123_frame_t dev->frame` is 74 bytes
   (`adv_touch_info(1) + reserved(1) + gesture(1) + keys(1) + areas[10]*7`; 
`st7123.c:221-228`,
   `ST7123_MAX_TOUCH_AREAS=10`, `ST7123_TOUCH_AREA_SIZE=7`), inside the 
heap-allocated `dev`
   (`kmm_zalloc`, `:916`). With `max_touches = 0xff`, `framelen = 4 + 255*7 = 
1789`, i.e. **1715 bytes
   written past the `frame` field**. Note this is 1715 bytes past the *field*, 
not past the whole
   allocation: `frame` is an embedded member of the larger heap-allocated 
`dev`, so the first ~300 of
   those bytes still land **inside** `dev` (corrupting sibling state — 
`device_caps`, `lastx[10]`,
   `lasty[10]`, `sample_buf[]`, etc.), and only the remaining ~1400-byte tail 
beyond `sizeof(*dev)` is a
   true out-of-bounds heap write. Both effects are memory corruption; the 
earlier phrasing "1715-byte
   heap overflow" overstated the portion that actually escapes the allocation.
   
   Secondary OOB writes in the same worker when `maxpoint > 10`: 
`dev->lastx[i]`/`dev->lasty[i]`
   (`:667-668`, `int16_t[10]`) and `sample->point[npoints++]` (`:680`, 
`sample_buf` sized
   `SIZEOF_TOUCH_SAMPLE_S(10)`).
   
   `st7123_probe_device()` runs during `st7123_register()` at boot/driver init; 
the oversized frame
   read fires on the **first touch interrupt** (`st7123_interrupt` → HPWORK → 
`st7123_data_worker`).
   No userspace `open()`/`read()` is required — the corruption is driven 
entirely by the I2C
   peripheral. Gated by `CONFIG_INPUT_ST7123`. The bug is present in **all 
build configurations**
   (independent of `CONFIG_DEBUG_ASSERTIONS`).
   
   **Why this is a bug (smoking gun): the clamp is promised in a comment but 
never implemented.**
   The header comment claims the value is clamped:
   
   ```c
   /* drivers/input/st7123.c:79-82 */
    * Maximum number of touch areas this driver is able to report.  The value
    * read back from ST7123_TOUCH_MAX_TOUCHES is clamped to this limit so that a
    * bogus register value can never overrun the frame or sample buffers.
   #define ST7123_MAX_TOUCH_AREAS         10
   ```
   
   No `min()` / `if (max_touches > ST7123_MAX_TOUCH_AREAS)` exists anywhere in 
the file. Sibling
   touch drivers do clamp: `drivers/input/ft5x06.c:243` gates on
   `if (sample->tdstatus <= FT5X06_MAX_TOUCHES)` and `ft5x06.c:500-503` clamps 
`ntouches` to the
   caller buffer; `drivers/input/mxt.c:1017` bounds its report-id index. ST7123 
omits the
   equivalent upper clamp entirely.
   
   Steps:
   1. Build with `CONFIG_INPUT_ST7123`.
   2. A malicious/compromised ST7123 controller reports `max_touches = 0xff` in 
its capability block.
   3. On the first touch interrupt the driver issues a burst read of `framelen 
= 4 + 255*7 = 1789`
      bytes into the 74-byte `dev->frame`, overflowing by 1715 bytes.
   
   An AddressSanitizer build with `max_touches = 0xff` and the burst read into 
the 74-byte frame
   reports:
   
   ```
   heap-buffer-overflow WRITE of size 1789
   ```
   
   **Suggested fix:** actually implement the clamp the comment promises, at 
registration (and/or in the
   worker):
   
   ```c
   if (priv->device_caps.max_touches > ST7123_MAX_TOUCH_AREAS)
     {
       priv->device_caps.max_touches = ST7123_MAX_TOUCH_AREAS;
     }
   ```
   
   ### 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: Drivers]
   
   ### 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