CVE-2021-38645修复后的内核崩溃问题复盘
近期在处理CVE-2021-38645漏洞修复时,遇到一个典型的内核崩溃问题。该漏洞涉及Linux内核中的内存管理子系统,主要影响x86_64架构下的内存映射操作。
问题现象
在应用官方补丁后,系统在高负载场景下频繁出现内核崩溃(Kernel Panic),错误信息显示为BUG: unable to handle kernel NULL pointer dereference。通过dmesg分析,定位到问题出现在__put_page()函数中对页表项的处理逻辑。
复现步骤
# 1. 创建测试环境
sudo apt install linux-image-$(uname -r)-dbg
# 2. 编译测试程序
#include <sys/mman.h>
#include <unistd.h>
int main() {
char *addr = mmap(NULL, 1024*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
for (int i = 0; i < 1000000; i++) {
volatile char c = addr[i % (1024*1024)];
addr[i % (1024*1024)] = c;
}
return 0;
}
# 3. 运行测试
./test_program &
根本原因
该问题源于补丁对page->mapping字段的处理不完整,特别是在内存回收时未正确判断页是否属于匿名映射。通过查看内核源码,发现__put_page()函数中缺少对空指针的检查。
解决方案
建议在内核配置中启用以下选项:
- CONFIG_DEBUG_PAGEALLOC=y
- CONFIG_PAGE_OWNER=y
同时修改内核启动参数:
GRUB_CMDLINE_LINUX="page_owner=1 debug"
对于生产环境,应使用经过充分测试的内核版本,避免直接应用未经生产验证的补丁。建议通过内核维护者邮件列表确认修复的有效性。

讨论