Submeter #844591: RT-Thread v5.0.2 Out-of-bounds Writeinformação

TítuloRT-Thread v5.0.2 Out-of-bounds Write
DescriçãoI have already reported this vulnerability in the project's GitHub issue tracker for review by the maintainers. The report is provided below. # SWM341 CAN receive path trusts raw DLC and writes past fixed receive buffers ## Describe the bug The SWM341 CAN receive path copies the raw hardware DLC value into fixed 8-byte CAN receive buffers without clamping it to the classic CAN payload size. The external input boundary is the CAN controller receive frame. When a frame arrives from the CAN bus, the controller exposes attacker-controlled frame metadata and payload through `CANx->FRAME.INFO` and `CANx->FRAME.DATA[]`. The low 4 bits of `CANx->FRAME.INFO` are used as the DLC. That external DLC value flows directly into a loop bound and causes an out-of-bounds write when it is greater than 8. The concrete data flow is: ```text external CAN frame -> CAN controller RX register CANx->FRAME.INFO[DLC] -> CAN_Receive(): msg->size -> loop bound for msg->data[i] -> out-of-bounds write when i == 8 and msg->size > 8 -> swm_can_recvmsg(): pmsg->len -> loop bound for pmsg->data[i] -> out-of-bounds write when i == 8 and pmsg->len > 8 ``` The RT-Thread CAN message type used when `RT_CAN_USING_CANFD` is not enabled stores only 8 payload bytes: ```text components/drivers/include/drivers/dev_can.h:510 components/drivers/include/drivers/dev_can.h:526 ``` However, the SWM341 low-level receive routine extracts a 4-bit DLC value from the CAN frame information register: ```c #define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) /* External input: DLC bits from the received CAN frame. */ msg->size = (CANx->FRAME.INFO & CAN_INFO_DLC_Msk) >> CAN_INFO_DLC_Pos; ``` and then uses that value directly as a byte count: ```c /* * Overflow trigger: * msg->data has valid indexes [0..7]. * If the external DLC is 9..15, the iteration with i == 8 writes * msg->data[8], which is past the end of CAN_RXMessage.data. */ for(i = 0; i < msg->size; i++) { /* CANx->FRAME.DATA[] is the external CAN payload register. */ msg->data[i] = CANx->FRAME.DATA[i+2]; } ``` `CAN_RXMessage.data` is only 8 bytes: ```c typedef struct { uint32_t id; uint8_t format; uint8_t remote; uint8_t size; uint8_t data[8]; } CAN_RXMessage; ``` The higher-level SWM341 RT-Thread driver then copies the same unchecked length into `struct rt_can_msg.data[8]`: ```c CAN_RXMessage CAN_RXMsg; CAN_Receive(can_dev->can_cfg->CANx, &CAN_RXMsg); /* CAN_RXMsg.size is derived from the external CAN DLC. */ pmsg->len = CAN_RXMsg.size; /* * Second overflow point: * pmsg points to RT-Thread's struct rt_can_msg. * pmsg->data also has valid indexes [0..7]. * If pmsg->len is still 9..15, i == 8 writes pmsg->data[8]. */ for(i = 0; i < pmsg->len; i++) { pmsg->data[i] = CAN_RXMsg.data[i]; } ``` The interrupt path reaches this driver callback through the generic RT-Thread CAN ISR: ```c /* Stack object inside rt_hw_can_isr(). */ struct rt_can_msg tmpmsg; /* swm_can_recvmsg() receives &tmpmsg as pmsg. */ ch = can->ops->recvmsg(can, &tmpmsg, no); ... rt_memcpy(&listmsg->data, &tmpmsg, sizeof(struct rt_can_msg)); ``` So a received classic CAN frame whose raw DLC code is 9..15 can corrupt stack memory in the ISR receive path before the message is copied into the RT-Thread RX FIFO. Locations: ```text bsp/synwit/libraries/SWM341_CSL/CMSIS/DeviceSupport/SWM341.h:2268 bsp/synwit/libraries/SWM341_CSL/CMSIS/DeviceSupport/SWM341.h:2269 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.h:85 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.h:89 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.h:90 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.c:240 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.c:246 bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.c:248 bsp/synwit/libraries/SWM341_drivers/drv_can.c:413 bsp/synwit/libraries/SWM341_drivers/drv_can.c:416 bsp/synwit/libraries/SWM341_drivers/drv_can.c:438 bsp/synwit/libraries/SWM341_drivers/drv_can.c:440 bsp/synwit/libraries/SWM341_drivers/drv_can.c:442 bsp/synwit/libraries/SWM341_drivers/drv_can.c:453 bsp/synwit/libraries/SWM341_drivers/drv_can.c:466 components/drivers/can/dev_can.c:982 components/drivers/can/dev_can.c:998 components/drivers/can/dev_can.c:1039 components/drivers/include/drivers/dev_can.h:526 ``` ## Steps to reproduce I have not reproduced this on physical SWM341 hardware yet. I verified the source-level bug with a standalone reduced check that preserves the relevant register decode and fixed-buffer copy semantics. The source-level trigger is: ```text CANx->FRAME.INFO DLC bits = 9..15 RT_CAN_USING_CANFD = not enabled BSP_USING_CAN = enabled BSP_USING_CAN0 or CAN1 = enabled ``` Reduced check: ```c #include <stdint.h> typedef struct { uint32_t INFO; uint8_t DATA[16]; } CAN_Frame; typedef struct { CAN_Frame FRAME; } CAN_TypeDef; typedef struct { uint32_t id; uint8_t format; uint8_t remote; uint8_t size; uint8_t data[8]; } CAN_RXMessage; #define CAN_INFO_DLC_Pos 0 #define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) void CAN_Receive(CAN_TypeDef *CANx, CAN_RXMessage *msg) { uint32_t i; /* External input: raw DLC from the received CAN frame. */ msg->size = (CANx->FRAME.INFO & CAN_INFO_DLC_Msk) >> CAN_INFO_DLC_Pos; for (i = 0; i < msg->size; i++) { /* OOB when can.FRAME.INFO makes msg->size > 8 and i reaches 8. */ msg->data[i] = CANx->FRAME.DATA[i + 2]; } } int main(void) { CAN_TypeDef can = {0}; CAN_RXMessage msg = {0}; can.FRAME.INFO = 15; /* external DLC value 15 */ CAN_Receive(&can, &msg); return 0; } ``` Compile it with AddressSanitizer, for example: ```text clang -x c -fsanitize=address -O0 -g repro.c -o repro && ./repro ``` Changing the receive path to clamp or reject DLC values above 8 avoids the ASan report. ## Relevant log output AddressSanitizer reports a stack buffer overflow on the write into `CAN_RXMessage.data`: ```text ERROR: AddressSanitizer: stack-buffer-overflow WRITE of size 1 #0 CAN_Receive ... repro.c #1 main ... repro.c This frame has 2 object(s): [..] 'can' [..] 'msg' <== Memory access overflows this variable SUMMARY: AddressSanitizer: stack-buffer-overflow in CAN_Receive ``` ## Impact Potential memory corruption from an externally supplied CAN frame on SWM341 boards when the CAN driver is enabled. The attacker-controlled value is the raw DLC field observed by the CAN controller. If the controller reports DLC values 9..15 to software, the driver first writes beyond the local `CAN_RXMessage.data[8]` buffer and then may also copy beyond `struct rt_can_msg.data[8]` in the RT-Thread receive callback. This is especially relevant for RTOS deployments because CAN traffic often crosses trust boundaries, and the vulnerable path executes from the interrupt-driven receive flow. ## Environment ```text Initial RT-Thread commit checked: c39e92f4c1 Checked tree description: v5.0.2-2360-gc39e92f4c1-dirty Affected driver: bsp/synwit/libraries/SWM341_drivers/drv_can.c Affected low-level CAN code: bsp/synwit/libraries/SWM341_CSL/SWM341_StdPeriph_Driver/SWM341_can.c Affected board family: Synwit SWM341 Target hardware: not tested on board yet Verification: host-side AddressSanitizer semantic check ``` The board configuration exposes this driver when CAN is enabled: ```text bsp/synwit/swm341-mini/board/Kconfig:115 menuconfig BSP_USING_CAN bsp/synwit/swm341-mini/board/Kconfig:120 config BSP_USING_CAN0 bsp/synwit/swm341-mini/board/Kconfig:123 config BSP_USING_CAN1 ``` The currently checked default `.config` has this board's CAN options disabled: ```text bsp/synwit/swm341-mini/.config:247 # CONFIG_RT_USING_CAN is not set bsp/synwit/swm341-mini/.config:1415 # CONFIG_BSP_USING_CAN is not set ``` ## Additional context A fix should validate the DLC before it is used as a copy length. For classic CAN, the code should either reject/drop frames whose raw DLC code is above 8 or clamp the payload length to 8 before copying: ```c msg->size = (CANx->FRAME.INFO & CAN_INFO_DLC_Msk) >> CAN_INFO_DLC_Pos; if (msg->size > 8) { msg->size = 8; } ``` The same invariant should be preserved in `swm_can_recvmsg()` before writing `pmsg->len` and before copying into `pmsg->data`.
Fonte⚠️ https://github.com/RT-Thread/rt-thread/issues/11425
Utilizador
 Zephyr Saxon (UID 80853)
Submissão01/06/2026 08h41 (há 1 mês)
Moderação03/07/2026 15h51 (1 month later)
EstadoAceite
Entrada VulDB376114 [RT-Thread até 5.0.2 SWM341 CAN SWM341.h CAN_Receive Excesso de tampão]
Pontos20

Interested in the pricing of exploits?

See the underground prices here!