wait3() 系统调用作为 Setuid 程序中的侧信道:nvidia-modprobe 案例研究 (CVE-2024-0149)
#local #setuid #CVE目录
- 1) 引言
- 2)
wait3()作为 Setuid 程序中的侧信道 - 3) 文件存在性测试 (CVE-2024-0149)
- 4) Bug修复
- 5) CVE 分配
- 6) 其他软件包
- 7) 时间线
- 8) 参考资料
1) 引言
nvidia-modprobe 是专有的 Nvidia GPU 显示驱动程序的 setuid-root 辅助工具,用于加载内核模块并创建用户空间 GPU 访问所需的字符设备。通常,驱动程序通过 udev 来完成此操作。然而,内核许可限制禁止 Nvidia 的专有内核模块生成 uevent,而 uevent 是 udev 工作所必需的。因此,需要此特殊辅助工具。
我们在 openSUSE 中审查了 nvidia-modprobe,作为我们白名单流程的一部分,该流程要求对所有新引入的 setuid 二进制文件进行审计。我们审查的版本是 550.127.05,本报告基于该版本。上游在版本 550.144.03 中发布了 bug 修复和一个 安全公告。
2) wait3() 作为 Setuid 程序中的侧信道
与 waitpid() 类似,wait3() 系统调用允许调用进程获取子进程的状态信息。与 waitpid() 不同的是,wait3() 还返回资源使用信息。此调用返回的测量值包括 CPU 时间、内存消耗以及较低级别的详细信息,例如子进程运行期间发生的次要和主要页面错误的数量。另请参阅 man 2 getrusage。
令人惊讶的是,wait3() 也适用于 setuid 子进程,泄露了大量关于以提升权限运行的目标程序行为的信息。
尝试此操作的一种便捷方法是使用 GNU Time,这是一个小型实用程序,它会启动目标进程并打印 wait3() 的输出,例如
/usr/bin/time -v nvidia-modprobe
3) 文件存在性测试 (CVE-2024-0149)
在 nvidia-modprobe 的情况下,我们可以利用 wait3() 进行文件存在性测试。
使用选项 -f NVIDIA-CAPABILITY-DEVICE-FILE(任意路径)执行时,nvidia-modprobe 会执行以下步骤:
- 尝试以 root 身份打开提供的路径
- 如果路径确实存在
- 读取一行或多行
- 解析每一行(安全实现)
- 静默退出,返回码 0
- 如果路径不存在
- 静默退出,返回码 0
- 如果路径确实存在
事实证明,读取所提供路径的第一行有时会触发次要页面错误。页面错误的数量在多次执行中并非完全恒定,这取决于内核映射的页面是否脏。但是,如果文件不存在,则无法读取,因此不会触发任何页面错误。我们可以反复执行 nvidia-modprobe,计算页面错误的众数,并推断提供的路径是否存在,即使调用者没有必要的文件系统权限。
简化示例
$ /usr/bin/time -q --format=%R nvidia-modprobe -f /root/.bash_history
80
$ /usr/bin/time -q --format=%R nvidia-modprobe -f /root/does/not/exist
79
输出会有所波动,但只需重复几次即可从众数获得可靠的信号。
4) Bug修复
上游发布了一个 bug 修复。此提交在尝试读取之前将查询路径限制在 /proc/driver/nvidia 下的文件,从而消除了信息泄露。
5) CVE 分配
上游为此问题分配了 CVE-2024-0149。
6) 其他软件包
考虑到这种侧信道攻击相对晦涩的性质,我们决定简要查看其他几个表现出类似使用模式的软件包。
shadowchsh:否
util-linuxmount -T:否umount:否
v4l-linux:是,但不需要wait3(),并且该问题已为人所知 (CVE-2020-1369)。
尽管我们没有找到此问题的其他实例,而且此漏洞的严重性相对较低,但它仍然是编写或审计 setuid 程序时需要牢记的众多陷阱之一。
7) 时间线
| 2024-10-02 | 我们注意到了这个问题,并在 bsc#1231257 中开始私下跟踪。 |
| 2024-10-09 | 我们通过电子邮件与 NVIDIA PSIRT 共享了信息,提供了协调披露。 |
| 2024-10-12 | 我们收到了来自 Nvidia 的初步确认。 |
| 2024-10-22 | 经过富有成效的讨论,主要是关于一些旁敲侧击的问题,我们同意 2025 年 1 月 16 日作为协调发布日期。 |
| 2025-01-16 | Nvidia 分配了 CVE-2024-0149。 |
| 2025-01-16 | Nvidia 发布了修复程序,作为版本 550.144.03 的一部分。 |