CVE-2025-22126漏洞分析与复现
Cheater 发表于 北京 漏洞分析 1059浏览 · 2025-06-04 10:28

CVE-2025-22126漏洞分析与复现

漏洞分析

看了下CVE的commit信息,很容易就能了解漏洞的关键所在。

漏洞位于drivers/md/md.c:9676的md_notify_reboot函数。

在循环对每一个mddev进行操作的时候,使用的是list_for_each_entry_safe宏。

C
复制代码
当all_mddevs_lock上锁时,就不允许其他异步函数再去访问all_mddevs,这一步是十分安全的。

但是上面的代码可以看到,在mddev_get之后就会解锁开放对all_mddevs的访问,如果使用list_for_each_entry来进行遍历,那这一步是没有问题的,毕竟在整个mddev访问阶段都是在上锁期间或者get后,mddev都不可能被释放。

但这里使用的确实list_for_each_entry_safe宏,该宏定义如下:

C
复制代码
可以看到该宏会优先保存next指针到n变量中,方便下次迅速访问。

但这个宏配合刚刚的操作就会产生漏洞,因为n保存next指针,也就是此时mddev1、mddev2前后两个mddev都被引用了,却只对mddev1进行了get,这就导致下面标记的这个期间,all_mddevs没有上锁,mddev2又没有get保护,此时我们释放mddev2是完全可以的。

释放完mddev2之后,list_for_each_entry_safe再去取mddev2就会导致uaf。

mddev是一个blk设备(块设备),可通过cat /proc/devices查看对应的设备号,然后通过mknod对改设备注册虚拟文件。(mknod /dev/mddev b 设备号 0)

按照断点情况,往/dev/mddev写入内容会触发probe探测函数,并会创建一个/dev/md0设备文件,open该设备文件会触发md_open。

而我们的目的是,先触发probe创建2个设备文件,之后在触发notify_reboot期间调用free_disk释放指定设备文件。

编译新版内核的时候要开启x2apic选项,防止调试的时候一直interrupt在apic函数。

RAID

RAID 级别
功能描述
典型用途
Linear
简单串联磁盘,无冗余或条带化
合并多个小磁盘为大容量设备
RAID 0
条带化(Stripe),提升读写性能
高性能存储,无冗余需求
RAID 1
镜像(Mirror),数据完全复制
高可用性,容忍单盘故障
RAID 5
分布式奇偶校验,兼顾性能与冗余
平衡存储效率与容错能力
RAID 6
双奇偶校验,容忍双盘故障
对数据安全性要求极高的场景
RAID 10
RAID 1 + RAID 0 的组合(先镜像再条带)
高性能+高冗余

mddev

md块设备核心作用就是将多个小磁盘统一管理,以此方便迅速的操作磁盘资源。

要先mknod /dev/md0 b 9 0为块设备创建节点。

然后需要使用mdadm工具为来创建并管理。

因为我们使用的是qemu运行bzImage,所以需要通过如下方式来创建多个磁盘并导入。

通过如上三个步骤我们成功的创建了三个设备,此时只需要在md_notify_reboot期间,删除md2即可触发UAF。

漏洞复现

md_notify_reboot是notifier_block结构体的函数成员,当设备出现故障时会触发。

根据函数名可以知道,系统在reboot的时候就会触发该函数。

链子大概就是:

因为是条件竞争,所以这里我还是通过修改内核源码来扩大时间差,从而增加竞争可能性。

我对md_notify_reboot进行了如下改动,加了个循环延迟:

之后我们只需要简单构造这么个poc。

然后通过nohup命令让程序在后台运行poc程序,之后再exit触发poweroff的reboot。

然后程序在循环延迟期间,poc程序调用mdadm --stop /dev/md0触发md_free_disk释放mddev。



循环延迟结束后,继续遍历下一个mddev,这里可以看到获取的mddev和刚刚释放的是一样的。



slub-dump也能看到该堆块已经被释放了,同时next指针被修改成了0.



成功触发崩溃异常。



总结

漏洞的关键点在于list_for_each_entry_safe宏的滥用,该宏会同时获取current以及next指针,而在循环过程中一般只会对current指针加引用并释放全局锁(错误认为只对current指针加引用即可保证安全性),却忘记了next指针已经被获取,从而可通过异步释放next指针,导致UAF漏洞。

这个漏洞面对我而言也是很新颖的,无论是list_for_each_entry_safe宏还是其他类似取双指针的操作,都很容易出现UAF漏洞,可以深究。



0 条评论
某人
表情
可输入 255