CVE-2023-53584CVE-2023-53584是Linux内核UBIFS(Unsorted Block Image File System)文件系统中存在的一个高可用性影响漏洞。该漏洞位于fs/ubifs/file.c文件的ubifs_releasepage()函数中,由于代码中存在ubifs_assert(0)断言检查,在特定竞态条件下会触发断言失败,导致UBIFS文件系统切换到只读模式,从而使系统丧失写入能力,造成拒绝服务攻击。该漏洞的CVSS评分为5.5,属于中危级别,攻击向量为本地攻击,攻击者需要具备低权限即可触发,无需用户交互。漏洞的根本原因是UBIFS在处理页面释放时,对页面状态的预期与实际可能出现的状态存在不一致。具体来说,UBIFS正常情况下页面只有两种状态:Dirty+Private或Not Dirty+Not Private。但在并发操作场景下(如写入、截断和fadvise操作同时进行),页面可能进入Private但Not Dirty的异常状态,此时调用ubifs_releasepage()会触发断言失败。Linux内核开发团队已通过移除该断言并增加对异常状态的正确处理来修复此问题。
该漏洞的技术原理涉及UBIFS文件系统中页面状态管理的竞态条件问题。UBIFS正常预期页面有两种状态组合:1) Dirty且Private(脏私有页面);2) Not Dirty且Not Private(非脏非私有页面)。然而在以下竞态条件下,页面可能进入Private但Not Dirty的异常状态:
1. 进程PA调用ubifs_write_end()设置页面为Private状态,然后通过__set_page_dirty_nobuffers()将其标记为Dirty;
2. write_cache_pages()开始处理该页面,调用clear_page_dirty_for_io()清除Dirty标记;
3. 在ubifs_writepage()执行期间,进程PB调用do_truncation()进行截断操作,将i_size设置为0;
4. 由于page->index > end_index,writepage流程直接跳到out标签处释放页面锁,但此时页面仍保留Private标志;
5. 进程PC调用generic_fadvise(),通过invalidate_inode_page()->try_to_release_page()调用ubifs_releasepage();
6. ubifs_releasepage()中的ubifs_assert(c, 0)断言触发,文件系统切换到只读模式。
此漏洞利用需要本地低权限访问权限,攻击者可以通过精心设计的并发I/O操作(包括write、truncate和fadvise64系统调用)来触发该竞态条件。触发后文件系统将变为只读模式,影响系统的可用性。