首页 / 资讯中心 / 文章详情

内核地址随便写:RT-Thread 四单同型缺陷同一个根因

内核地址随便写:RT-Thread 四单同型缺陷同一个根因 ★ FEATURED ARTICLE
10 月底到 11 月初RT-Thread 社区连续报出四笔 RT-Smart 缺陷终端、块设备、管道、邮箱——形态完全一致用户态进程可以把一个内核地址当参数传下去内核不校验直接读写。其中 mailbox 那单最严重等价于一个任意内核内存读写的原语。这篇文章把四单放在一起看为什么会反复出现同一个错根源不在某一行代码在移植策略。 全文 8 章 · 6 张图 · 一条主线fops 层默认参数已是内核地址用户态入口没补转换层 一、四单缺陷一个模子先把时间线摆出来数据来自 RT-Thread 开源社区日报报告者 XueDugu日期缺陷位置危害10-28#11937终端 ioctl丢 FreeBSD copyin 前提可读写内核内存10-29#11952块设备 ioctl24 字节分区表写进攻击者指定的内核地址10-30#11958管道 FIONREAD环缓冲长度直接写进用户给的指针10-31#11960邮箱 sys_mb_send伪造内核对象等价任意内核读写四单影响版本一致v5.0.0 至 v5.3.0 与 master5.4.0-dev引入提交都指向 2022-12-03 的 RT-Smart 系统调用边界调整ecf2d821。在 QEMU 上即可复现无需特殊硬件。ecf2d8212022-12 RT-Smart 系统调用边界调整fops 适配层沿用老假设参数已是内核地址终端 ioctl#11937块设备 ioctl#11952管道 ioctl#11958邮箱 sys_mb_send#11960用户态可指定内核地址任意读写原语 二、以 mailbox 为例漏洞长什么样看最严重的 #11960。mailbox 的系统调用入口sys_mb_send()把用户传进来的内核对象指针直接转发给内核 mailbox API没有校验这个对象是不是属于调用者的 LWP、是不是 mailbox、是不是落在内核内存。于是一个非特权进程可以构造伪造对象让内核按自己的规则去读写它——效果等价于任意内核读写原语。报告的验证做了两层QEMU 全系统运行证明用户态到内核的越界路径树莓派 Pico 2 WRP2350在板级验证 mailbox API 原语本身。攻击路径画出来是这样的内核内存内核 mailbox APIsys_mb_send()非特权进程内核内存内核 mailbox APIsys_mb_send()非特权进程任意内核读写原语成立传入伪造对象指针不校验归属/类型/地址范围直接转发指针按对象规则读写对比一下正确做法BSD 的 ioctl 体系里用户指针进入内核必须先过copyin/copyout——把数据在用户地址空间和内核缓冲之间显式搬运。这层转换不是可选项是边界本身。 三、为什么会连续犯四次移植丢掉了前提四单的共同成因一句话就能说清RT-Smart 的 ioctl 适配层默认参数已经是内核地址而用户态入口并没有做这一层转换。这属于典型的移植性缺陷。原有代码跑在内核态直连场景参数确实是内核地址RT-Smart 引入用户态隔离后fops 层代码原样搬过来前提却已经不成立了。管道那单的写法特别典型用户进程ioctl(fd, FIONREAD, ptr)sys_ioctl()不 copyout 直接转发pipe_fops直接写 *(int*)args写入用户指定的任意内核地址值得注意的还有同型缺陷第三次出现这个事实——终端、块设备、管道三单里*((int *)args) ...这种直接解引用用户指针的写法出现了三次。说明这不是某个人手滑而是适配层缺少一个系统性的入口约定所有来自用户态的指针必须先校验再使用这个约定没有落在代码结构里就只能在代码审查里撞运气。 四、第三单里藏着的乘法回绕poll 的 5.3 亿项遍历同一批报告里还有个细节值得单独讲sys_poll 的计数乘法回绕#11954 修 #11925。用户传入 nfdspollfd 数量内核用它乘以结构体大小算缓冲区。32 位下乘法会回绕nfds 0x20000001、每项 8 字节乘积被截成 8——分配校验按 8 字节通过遍历却按原始数量走5.3 亿项读写全部落在分配块之外。修法是所有拿用户数量算大小的地方先判回绕是否用户传入 nfdsnfds 大于SIZE_MAX / sizeof?返回 EINVAL计算缓冲区大小kmem_get 分配遍历 nfds 项读写受控同一批在途的还有 sys_sigaction 校验信号号、sys_sendmsg 校验 msg_iovlen——共同点都是把用户态传入的编号、长度、指针在进入内核逻辑前先校一遍。这条线收完RT-Smart 的系统调用边界才算真正立起来。 五、修复进展谁修了谁还挂着截至 11 月初的社区日报四单的状态各不相同终端/块设备/管道/邮箱四单终端侧 #11941块设备/管道/邮箱577/-52 六文件合入后闭环持续暴露中已报告有修复提案无人认领待评审终端修复提案 #11941 已于 10-28 提交6 个文件、577/-52引入 copyin/copyout块设备、管道、邮箱尚无对应修复提案处于无人认领状态poll 回绕#1195428 行已在 10-30 提交与 sys_sendmsg 的校验写法保持一致。对用 RT-Smart 的团队当下的实际建议用户态进程若跑不受信代码四条路径全是攻击面跑自有可信代码则风险可控但建议关注 #11941 的合入进展合入后尽快跟进基线。 六、更大背景RT-Smart 正在被系统性清账把镜头拉远这批缺陷是 RT-Thread 近期RT-Smart 边界清账的一部分。10 月 29 日qemu-virt64 两个 BSP 曾短暂启用 Smart七个半小时后又被收回默认配置——维护者把 Smart 定位为utest 配置覆盖层而非 BSP 默认项。同期的其他动作lwp 系统调用按子系统拆成 20 个文件lwp_syscall.c 一次删掉 11638 行clang-format 锁版本后全量重排 73 个内核文件dlmodule 收掉挂了四年多的 #5705。10-2810-2810-2810-2810-2910-2910-2910-2910-3010-3010-3010-3010-31终端ioctl报告终端修复提案块设备ioctl报告Smart收回默认配置lwp拆分20文件管道ioctl报告邮箱对象报告边界缺陷架构调整RT-Thread 10 月底 RT-Smart 相关动作线架构拆分和边界修复是同一件事的两面先让代码能按子系统定位边界修复才不必在万行文件里穿梭。 七、给嵌入式团队的三条启示移植带前提。代码搬家时参数来自哪里这个前提变了所有直接解引用的路径都要重审。这不是风格问题是安全边界问题。同型缺陷第三次出现就该修结构。三次手滑说明缺的不是细心是入口约定。把用户指针必须先校验做成适配层的强制模式封装宏、静态检查、代码模板比在 review 里靠人眼可靠得多。QEMU 复现是最低成本的安全验证。四单全部在 QEMU 上复现。RTOS 团队把用户态 fuzz 一下 ioctl 入口加进 CI成本低到没有理由不做。75%25%四单缺陷的成因占比按报告归类fops 层直接解引用用户指针计数乘法回绕未校验✍️ 八、写在最后四单缺陷技术上都不复杂——每一单的修复都不会超过几十行。真正值得注意的是它们以完全相同的形态连续出现四次横跨四个子系统时间跨度四天。这是架构层面在喊话RT-Smart 的用户态边界还欠一层系统性的入口约定。社区正在还这笔债lwp 拆分、#11941、poll 校验对使用者来说盯紧这批修复的合入节奏比多看十篇内核科普都有用。数据来源RT-Thread 开源社区每日动态kubuds.cn2026-10-28 至 11-02缺陷与提案编号以 GitHub 主仓库为准。截至发文块设备/管道/邮箱三单尚无修复提案。
阅读完成 · 觉得有帮助?
咨询建站