Repository navigation
Description
RT-Thread Version
v5.3.0 through current master 08cad4ee9cda4ea30bc3dfab1d71318c1c50f749.
The vulnerable code was introduced by 5abecc1fd0c3 on 2025-12-12.
The current graphic.c blob is
14de5a6cda124e86c87991d298501cec42d9bf43.
Affected area
Device drivers / Graphic
Hardware-BSP vendor
Other: QEMU ramfb and Raspberry Pi Pico 2 W / RP2350
Architecture
ARM / AArch64
Board and hardware details
The RT-Smart user-to-kernel boundary was reproduced on
qemu-virt64-aarch64 with the stock QEMU ramfb device. The board-level
kernel API primitive was reproduced on a Raspberry Pi Pico 2 W (RP2350 ARM
Secure) over USB CDC.
Develop Toolchain
RT-Thread AArch64 musl GCC for the RT-Smart kernel and user ELF; QEMU
full-system execution. The Pico 2 W image uses Pico SDK 2.3.1 and ARM GNU GCC
10.3.1.
Describe the bug
_graphic_read() and _graphic_write() accept a signed device offset without
checking pos >= 0 or pos < framebuffer_len:
res = rt_min_t(rt_ssize_t, plane->framebuffer_len - pos, size);
if (res > 0)
{
rt_memcpy(plane->framebuffer + pos, buffer, res);
}RT-Smart pread64() and pwrite64() pass the offset through DFS to the
graphic device. The current rw_verify_area() rejects a negative position only
when count >= -pos. Therefore, count=8 with pos=-210456 is accepted.
The graphic driver then computes framebuffer + pos outside the framebuffer
and copies to or from that address.
An unprivileged process can:
- Open
/dev/fb0. - Obtain the framebuffer kernel address through
RTGRAPHIC_CTRL_GET_INFO. - Set
pos = kernel_target - framebuffer. - Use
pread64()orpwrite64()to read or write an 8-byte kernel qword.
The code path is:
sys_pwrite64
-> pwrite
-> dfs_file_pwrite
-> dfs_devfs_write
-> rt_device_write
-> _graphic_write
-> memcpy(framebuffer + pos, ...)
_graphic_read() has the same missing offset validation.
Steps to reproduce
A. Pico 2 W board-level reproduction
This run uses a ready-to-flash RP2350 ARM Secure image (pico2_w, UF2 family
0xe48bff59, SHA-256
957a42259ff8d13767076f4ff8bc46dab2454e7c0b6065a4f550121a0ff94457).
The firmware registers a framebuffer through the official
rt_graphic_device_register() API and calls rt_device_write() with the
framebuffer base and a target in the same RAM:
- Flash the UF2 to a Pico 2 W.
- Open its USB CDC port at 115200 baud.
- Send
gfx_poc.
Expected: the negative framebuffer offset is rejected.
Actual:
gfx_poc: framebuffer=0x20002bc8 target=0x20001bc8 delta=-4096
gfx_poc: target before=0x00000000
gfx_poc: write ret=4 target_after=0x11223344
gfx_poc: CONFIRMED negative framebuffer offset write
The Pico is a 32-bit target, so its rt_ubase_t value occupies four bytes.
This hardware run proves the official graphic driver and device-write path
accepts a negative offset on a real RP2350.
B. RT-Smart user-to-kernel trust-boundary reproduction
- Build
bsp/qemu-virt64-aarch64withRT_USING_GRAPHIC=y. - Boot QEMU with the stock
-device ramfbmodel and a root filesystem
containing an unprivileged RT-Smart user ELF. - Open
/dev/fb0and queryRTGRAPHIC_CTRL_GET_INFO. - Compute a negative offset that points to a chosen mapped kernel address.
- Call
pwrite64()andpread64()with that offset.
Control with offset 0:
framebuffer=0xffff000000249000
delta=0
pread ret=8 old=0
pwrite ret=8
readback=0x1122334455667788
target restored; kernel alive
Attack targeting the graphic component's fbcon_map[0]:
framebuffer=0xffff000000249000
kernel_target=0xffff0000002159e8
delta=0xfffffffffffcc9e8
pread ret=8 old=0
pwrite ret=8
readback=0x1122334455667788
target restored; kernel alive
The PoC restores the target after verification.
Evidence
Three independent QEMU attack runs produced identical output. Their SHA-256 is:
87fbab834199e97b92a4c81e5187ae3e97937e4c95a7a2acd00c299c827af30a
GDB stopped in _graphic_write() with:
dev=0xffff000000248640 pos=-210456 buffer=0xffff000000475910 size=8
#0 _graphic_write
#1 rt_device_write
#2 dfs_devfs_write
#3 dfs_file_pwrite
#4 pwrite
#5 sys_pwrite64
#6 _SVC_Handler
A hardware watchpoint on fbcon_map showed:
Old value = 0
New value = 0x1122334455667788
The hardware reproduction is also linked from section A above. The RT-Smart
boundary proof uses 64-bit qwords on AArch64.
Impact
An unprivileged RT-Smart process can read and write kernel memory before the
framebuffer mapping. The primitive can be repeated to modify hooks, scheduler
state, object metadata, or other mapped kernel data.
Other additional context
- CVSS:3.1/
AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H= 8.8 - CWE-787, CWE-125, CWE-823
- Prerequisite: the build enables the graphic subsystem and exposes
/dev/fb0. This is normal for display products. The QEMU reproduction uses
the stockramfbdevice. - Related issue: [Security] pread() with a large negative offset bypasses rw_verify_area() causing OOB heap read in tmpfs (info leak / crash) #11737 reports the same negative-offset rule in the tmpfs
read path. This report is an incomplete-fix sibling in the graphic device
sink, not a claim that the DFS issue itself is newly discovered. - No existing issue or pull request was found for
_graphic_read,
_graphic_write, negative framebuffer offsets, orfb0arbitrary access. - Suggested structural fix: reject negative offsets in the graphic read/write
operations and enforce device-specific offset bounds at devfs/device
dispatch.
Activity
github-actions commentedon Nov 2, 2026
如需认领并处理此 Issue,请评论
/claim。To claim and work on this issue, comment
/claim.github-actions commentedon Nov 2, 2026
以下 Issue 可能与当前问题相关;这是自动检索结果,尚未确认重复:
The following issues may be related. These automated suggestions are not confirmed duplicates: