CVE-2025-39966CVE-2025-39966是Linux内核iommufd(IO Memory Management Unit File Descriptor)子系统中存在的一个高危Use-After-Free(UAF)漏洞。该漏洞源于iommufd在对象分配中止路径中对文件描述符生命周期的处理不当。具体而言,当分配新的iommufd对象在安装文件之前中止时,系统会调用fput()释放文件,然后立即调用kfree()释放对象。然而fput()并不会同步调用file_operations的release()回调,而是将文件放入工作队列延迟释放。由于iommufd对象与文件结构通过private_data相互关联,对象的生命周期依赖于文件的引用计数,这种异步释放机制导致了竞争条件:当工作队列最终执行release()回调并尝试递减引用计数时,对象可能已经被kfree(),从而触发Use-After-Free漏洞。该漏洞可被本地低权限用户利用,通过精心构造的ioctl调用触发竞争条件,实现内核内存的读写操作,可能导致权限提升、内核崩溃(DoS)或其他安全危害。
该漏洞的根本原因在于iommufd核心代码与对象实现之间的文件生命周期管理职责不清。在正常情况下,文件结构通过private_data指向iommufd_object,并持有该对象的users引用计数,确保只要文件存在,对象就不会被销毁。然而在异常处理路径中,当对象分配失败需要中止时,代码调用fput()释放文件后立即调用kfree()释放对象。由于fput()是异步操作(通过task_work机制延迟执行),release()回调可能在kfree()之后才被调用,此时访问已被释放的对象内存就会触发KASAN检测到的slab-use-after-free错误。具体的崩溃发生在iommufd_eventq_fops_release()函数中,当它尝试通过atomic_fetch_sub_release递减已被释放对象的引用计数时触发。修复方案是引入__fput_sync()机制,将文件生命周期的管理权统一交给iommufd核心代码,对象实现只需告知核心代码文件指针的位置,由核心代码负责在中止路径中同步调用release(),确保kfree()之前文件已被正确释放。攻击者可以通过构造特定的ioctl调用序列(如IOMMU_DESTROY相关操作)来触发竞争窗口,利用UAF实现内核地址空间内的任意读写。