Skip to content

Commit 548cfe7

Browse files
committed
drivers: input: crsf: contain out-of-bounds async rx-ready windows
A field fault traced to the CRSF RX_RDY path: the parser was handed a buffer window whose base pointer read a wild address, faulting in ISR context. The serial driver's async double-buffer accounting was audited and found self-consistent: the RX_RDY event reports a (buf, offset, len) window derived under lock from a single view, with offset and length bounded by the buffer length, so the wild base pointer cannot come from that accounting alone and the root mechanism could not be pinned in the serial layer. This guard is containment at the buffer owner, not a fix for a proven serial-driver defect. The CRSF driver supplies the two RX DMA buffers, so it can validate the event before trusting it: require the RX_RDY buffer to be one of those two buffers and the offset/len window to stay within CRSF_RX_BUF_SIZE before invalidating cache or parsing. Anything else is dropped so a stale or corrupt window can never reach crsf_process_bytes. Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
1 parent 5a57f9d commit 548cfe7

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

drivers/input/input_crsf.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,28 @@ static void crsf_uart_callback(const struct device *uart_dev, struct uart_event
459459
LOG_ERR("CRSF TX Aborted");
460460
break;
461461

462-
case UART_RX_RDY:
462+
case UART_RX_RDY: {
463+
uint8_t *rx_buf = evt->data.rx.buf;
464+
size_t rx_off = evt->data.rx.offset;
465+
size_t rx_len = evt->data.rx.len;
466+
467+
/*
468+
* The window must name one of our two RX buffers and stay inside
469+
* it, or the async event is corrupt and gets dropped.
470+
*/
471+
if ((rx_buf != data->rx_buf_a && rx_buf != data->rx_buf_b) || rx_len == 0 ||
472+
rx_off > CRSF_RX_BUF_SIZE || rx_len > (size_t)CRSF_RX_BUF_SIZE - rx_off) {
473+
LOG_DBG("Dropping out-of-range CRSF RX window");
474+
break;
475+
}
476+
463477
#ifdef CRSF_INVALIDATE_CACHE
464-
arch_dcache_invd_range(&evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len);
478+
arch_dcache_invd_range(&rx_buf[rx_off], rx_len);
465479
#endif
466480
/* Process received data chunk */
467-
crsf_process_bytes(dev, &evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len);
481+
crsf_process_bytes(dev, &rx_buf[rx_off], rx_len);
468482
break;
483+
}
469484

470485
case UART_RX_BUF_REQUEST:
471486
/* Provide the next buffer to keep reception continuous */

0 commit comments

Comments
 (0)