CVE-2023-53564CVE-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对即可。