CVE-2023-53558CVE-2023-53558是Linux内核rcu-tasks子系统中存在的一个锁上下文错误漏洞。该漏洞位于cblist_init_generic()函数中,在调用pr_info()打印日志信息时持有rtp->cbs_gbl_lock自旋锁。由于pr_info()底层调用printk()函数,而printk()在串行控制台输出过程中可能会获取其他锁并导致睡眠操作,这违反了自旋锁不能在持有期间睡眠的内核规则,从而触发"BUG: Invalid wait context"错误。
该漏洞在系统启动早期(内核初始化阶段)就会被触发,具体发生在rcu_init_tasks_generic()调用cblist_init_generic()的过程中。当swapper/0进程尝试获取port_lock_key(串行端口锁)时,系统检测到非法等待上下文,导致内核警告和潜在的系统挂起或崩溃。此漏洞影响系统的可用性,可能导致内核启动失败或系统不稳定,特别是在使用串行控制台的环境中。
根据CVSS 3.1评分,该漏洞评分为5.5分,属于中危级别。攻击向量为本地攻击(AV:L),需要低权限(PR:L),无需用户交互(UI:N),对机密性影响低(C:L),对完整性无影响(I:N),对可用性影响高(A:H)。这表明该漏洞虽然需要本地访问权限,但一旦触发可能导致系统完全不可用。
该漏洞的根本原因是Linux内核rcu-tasks子系统中cblist_init_generic()函数的不当锁使用。具体技术细节如下:
1. **漏洞位置**:kernel/rcu/tasks.h中的cblist_init_generic()函数
2. **触发原理**:在cblist_init_generic()函数中,pr_info()调用在持有rtp->cbs_gbl_lock自旋锁的情况下执行。pr_info()最终调用printk(),而printk()在串行控制台环境下会调用console_unlock(),进而调用console_emit_next_record()和serial8250_console_write(),这些函数会尝试获取port_lock_key自旋锁。
3. **锁依赖冲突**:形成了以下锁依赖链:
- swapper/0/1持有rcu_tasks.cbs_gbl_lock(等级2:2)
- _printk()持有console_lock(等级0:0)
- console_emit_next_record()持有console_owner(等级0:0)
- 尝试获取port_lock_key(等级3:3)
4. **错误检测**:内核的锁调试子系统(lockdep)检测到在原子上下文(自旋锁持有期间)尝试获取可能睡眠的锁,因此触发"Invalid wait context" BUG。
5. **修复方案**:将pr_info()调用移出持有cbs_gbl_lock的临界区,使其在锁释放后执行,避免在自旋锁上下文中调用可能睡眠的printk函数。
利用方式:由于该漏洞在内核初始化早期自动触发,攻击者无需特殊利用代码。任何使用受影响内核版本的系统在启动时(特别是配置了串行控制台的环境)都可能遇到此问题。