{"id":"CVE-2025-40271","state":"PUBLISHED","title":"fs/proc: fix uaf in proc_readdir_de()","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nfs/proc: fix uaf in proc_readdir_de()\n\nPde is erased from subdir rbtree through rb_erase(), but not set the node\nto EMPTY, which may result in uaf access.  We should use RB_CLEAR_NODE()\nset the erased node to EMPTY, then pde_subdir_next() will return NULL to\navoid uaf access.\n\nWe found an uaf issue while using stress-ng testing, need to run testcase\ngetdent and tun in the same time.  The steps of the issue is as follows:\n\n1) use getdent to traverse dir /proc/pid/net/dev_snmp6/, and current\n   pde is tun3;\n\n2) in the [time windows] unregister netdevice tun3 and tun2, and erase\n   them from rbtree.  erase tun3 first, and then erase tun2.  the\n   pde(tun2) will be released to slab;\n\n3) continue to getdent process, then pde_subdir_next() will return\n   pde(tun2) which is released, it will case uaf access.\n\nCPU 0                                      |    CPU 1\n-------------------------------------------------------------------------\ntraverse dir /proc/pid/net/dev_snmp6/      |   unregister_netdevice(tun->dev)   //tun3 tun2\nsys_getdents64()                           |\n  iterate_dir()                            |\n    proc_readdir()                         |\n      proc_readdir_de()                    |     snmp6_unregister_dev()\n        pde_get(de);                       |       proc_remove()\n        read_unlock(&proc_subdir_lock);    |         remove_proc_subtree()\n                                           |           write_lock(&proc_subdir_lock);\n        [time window]                      |           rb_erase(&root->subdir_node, &parent->subdir);\n                                           |           write_unlock(&proc_subdir_lock);\n        read_lock(&proc_subdir_lock);      |\n        next = pde_subdir_next(de);        |\n        pde_put(de);                       |\n        de = next;    //UAF                |\n\nrbtree of dev_snmp6\n                        |\n                    pde(tun3)\n                     /    \\\n                  NULL  pde(tun2)","publishedAt":"2025-12-06T21:50:53.266Z","updatedAt":"2026-08-05T12:09:04.518Z","severity":{"score":7.8,"label":"High","version":"3.1","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","source":"Linux"},"assigner":"Linux","products":["Linux Linux"],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"1d1596d68a6f11d28f677eedf6cf5b17dbfeb491","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"c81d0385500446efe48c305bbb83d47f2ae23a50","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"4cba73c4c89219beef7685a47374bf88b1022369","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"6f2482745e510ae1dacc9b090194b9c5f918d774","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"67272c11f379d9aa5e0f6b16286b9d89b3f76046","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"623bb26127fb581a741e880e1e1a47d79aecb6f8","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"03de7ff197a3d0e17d0d5c58fdac99a63cba8110","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"895b4c0c79b092d732544011c3cecaf7322c36a1","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["fs/proc/generic.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"3.19","status":"affected"},{"version":"0","status":"unaffected","lessThan":"3.19","versionType":"semver"},{"version":"5.4.302","status":"unaffected","lessThanOrEqual":"5.4.*","versionType":"semver"},{"version":"5.10.247","status":"unaffected","lessThanOrEqual":"5.10.*","versionType":"semver"},{"version":"5.15.197","status":"unaffected","lessThanOrEqual":"5.15.*","versionType":"semver"},{"version":"6.1.159","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.117","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.59","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.17.9","status":"unaffected","lessThanOrEqual":"6.17.*","versionType":"semver"},{"version":"6.18","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["fs/proc/generic.c"]}],"references":["https://git.kernel.org/stable/c/1d1596d68a6f11d28f677eedf6cf5b17dbfeb491","https://git.kernel.org/stable/c/c81d0385500446efe48c305bbb83d47f2ae23a50","https://git.kernel.org/stable/c/4cba73c4c89219beef7685a47374bf88b1022369","https://git.kernel.org/stable/c/6f2482745e510ae1dacc9b090194b9c5f918d774","https://git.kernel.org/stable/c/67272c11f379d9aa5e0f6b16286b9d89b3f76046","https://git.kernel.org/stable/c/623bb26127fb581a741e880e1e1a47d79aecb6f8","https://git.kernel.org/stable/c/03de7ff197a3d0e17d0d5c58fdac99a63cba8110","https://git.kernel.org/stable/c/895b4c0c79b092d732544011c3cecaf7322c36a1","https://cert-portal.siemens.com/productcert/html/ssa-253495.html"],"weaknesses":[],"ingestedAt":"2026-10-29T20:09:09.358Z","source":{"repository":"CVEProject/cvelistV5","path":"cves/2025/40xxx/CVE-2025-40271.json","commit":"556c9d3a8cd17e218bb8e452ba7cd619a384ff47"},"raw":{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2025-40271","state":"PUBLISHED","datePublished":"2025-12-06T21:50:53.266Z","dateUpdated":"2026-08-05T12:09:04.518Z","assignerShortName":"Linux","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateReserved":"2025-04-16T07:20:57.183Z"},"containers":{"cna":{"title":"fs/proc: fix uaf in proc_readdir_de()","descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nfs/proc: fix uaf in proc_readdir_de()\n\nPde is erased from subdir rbtree through rb_erase(), but not set the node\nto EMPTY, which may result in uaf access.  We should use RB_CLEAR_NODE()\nset the erased node to EMPTY, then pde_subdir_next() will return NULL to\navoid uaf access.\n\nWe found an uaf issue while using stress-ng testing, need to run testcase\ngetdent and tun in the same time.  The steps of the issue is as follows:\n\n1) use getdent to traverse dir /proc/pid/net/dev_snmp6/, and current\n   pde is tun3;\n\n2) in the [time windows] unregister netdevice tun3 and tun2, and erase\n   them from rbtree.  erase tun3 first, and then erase tun2.  the\n   pde(tun2) will be released to slab;\n\n3) continue to getdent process, then pde_subdir_next() will return\n   pde(tun2) which is released, it will case uaf access.\n\nCPU 0                                      |    CPU 1\n-------------------------------------------------------------------------\ntraverse dir /proc/pid/net/dev_snmp6/      |   unregister_netdevice(tun->dev)   //tun3 tun2\nsys_getdents64()                           |\n  iterate_dir()                            |\n    proc_readdir()                         |\n      proc_readdir_de()                    |     snmp6_unregister_dev()\n        pde_get(de);                       |       proc_remove()\n        read_unlock(&proc_subdir_lock);    |         remove_proc_subtree()\n                                           |           write_lock(&proc_subdir_lock);\n        [time window]                      |           rb_erase(&root->subdir_node, &parent->subdir);\n                                           |           write_unlock(&proc_subdir_lock);\n        read_lock(&proc_subdir_lock);      |\n        next = pde_subdir_next(de);        |\n        pde_put(de);                       |\n        de = next;    //UAF                |\n\nrbtree of dev_snmp6\n                        |\n                    pde(tun3)\n                     /    \\\n                  NULL  pde(tun2)"}],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"1d1596d68a6f11d28f677eedf6cf5b17dbfeb491","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"c81d0385500446efe48c305bbb83d47f2ae23a50","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"4cba73c4c89219beef7685a47374bf88b1022369","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"6f2482745e510ae1dacc9b090194b9c5f918d774","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"67272c11f379d9aa5e0f6b16286b9d89b3f76046","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"623bb26127fb581a741e880e1e1a47d79aecb6f8","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"03de7ff197a3d0e17d0d5c58fdac99a63cba8110","versionType":"git"},{"version":"710585d4922fd315f2cada8fbe550ae8ed23e994","status":"affected","lessThan":"895b4c0c79b092d732544011c3cecaf7322c36a1","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["fs/proc/generic.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"3.19","status":"affected"},{"version":"0","status":"unaffected","lessThan":"3.19","versionType":"semver"},{"version":"5.4.302","status":"unaffected","lessThanOrEqual":"5.4.*","versionType":"semver"},{"version":"5.10.247","status":"unaffected","lessThanOrEqual":"5.10.*","versionType":"semver"},{"version":"5.15.197","status":"unaffected","lessThanOrEqual":"5.15.*","versionType":"semver"},{"version":"6.1.159","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.117","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.59","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.17.9","status":"unaffected","lessThanOrEqual":"6.17.*","versionType":"semver"},{"version":"6.18","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["fs/proc/generic.c"]}],"references":[{"url":"https://git.kernel.org/stable/c/1d1596d68a6f11d28f677eedf6cf5b17dbfeb491"},{"url":"https://git.kernel.org/stable/c/c81d0385500446efe48c305bbb83d47f2ae23a50"},{"url":"https://git.kernel.org/stable/c/4cba73c4c89219beef7685a47374bf88b1022369"},{"url":"https://git.kernel.org/stable/c/6f2482745e510ae1dacc9b090194b9c5f918d774"},{"url":"https://git.kernel.org/stable/c/67272c11f379d9aa5e0f6b16286b9d89b3f76046"},{"url":"https://git.kernel.org/stable/c/623bb26127fb581a741e880e1e1a47d79aecb6f8"},{"url":"https://git.kernel.org/stable/c/03de7ff197a3d0e17d0d5c58fdac99a63cba8110"},{"url":"https://git.kernel.org/stable/c/895b4c0c79b092d732544011c3cecaf7322c36a1"}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH"},"scenarios":[{"lang":"en","value":"AV:L - The vulnerability is triggered entirely through local syscalls — `getdents64(2)` on a procfs directory racing against `unshare(2)`/rtnetlink operations that remove `/proc` entries. No network or remote-peer data is involved.\nAC:L - The attacker owns both sides of the race: one thread iterates `/proc/self/net/dev_snmp6` while another spins netdevice rename/unregister to erase entries, and the `dir_emit()` window can be stretched arbitrarily by backing the `getdents64` buffer with userfaultfd or FUSE so the reader stalls in `copy_to_user` while the neighbour pde is freed and the slab groomed. The sequence is unbounded and retryable.\nPR:L - Reading `/proc/self/net/dev_snmp6` requires no privilege at all, and the removal side needs only `CAP_NET_ADMIN` inside an attacker-created user+network namespace (`unshare -Urn`), which any unprivileged user obtains on default distro configurations. No real root in the init namespace is needed.\nUI:N - The attacker drives both the directory iteration and the proc-entry removal from its own threads; no victim action or cooperation is required.\nS:U - The corruption is confined to kernel heap objects managed by the same kernel security authority; there is no VM, IOMMU, or hypervisor boundary crossed.\nC:H - `dir_emit(ctx, de->name, de->namelen, ...)` reads the `char *name` pointer and `u8 namelen` out of the freed `proc_dir_entry` and copies up to 255 bytes from that pointer directly into the user's dirent buffer, giving a repeatable arbitrary-kernel-memory read into userspace once the slab object is reclaimed with attacker-influenced content.\nI:H - The use-after-free yields `refcount_inc()`/`refcount_dec_and_test()` on freed memory plus `pde_free()` performing `kfree(pde->data)`/`kfree(pde->name)` on pointers read from the reallocated object, providing arbitrary-free and heap-corruption primitives that are a standard basis for local privilege escalation.\nA:H - Dereferencing stale rbtree links into freed slab memory reliably produces a kernel oops/panic (as observed under stress-ng with getdents+tun), and the race can be re-run indefinitely to crash the system on demand."}]}],"providerMetadata":{"shortName":"Linux","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateUpdated":"2026-08-05T12:09:04.518Z"},"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"5.4.302"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"5.10.247"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"5.15.197"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"6.1.159"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"6.6.117"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"6.12.59"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"6.17.9"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.19","versionEndExcluding":"6.18"}]}]}],"x_generator":{"engine":"bippy-1.2.0"}},"adp":[{"affected":[{"vendor":"Siemens","product":"RUGGEDCOM RST2428P","defaultStatus":"unknown","versions":[{"version":"0","status":"affected","lessThan":"V4.0","versionType":"custom"}]}],"references":[{"url":"https://cert-portal.siemens.com/productcert/html/ssa-253495.html"}],"providerMetadata":{"shortName":"siemens-SADP","orgId":"0b142b55-0307-4c5a-b3c9-f314f3fb7c5e","dateUpdated":"2026-06-02T13:00:17.378Z"},"x_adpType":"supplier"},{"title":"CISA ADP Vulnrichment","metrics":[{"other":{"type":"ssvc","content":{"timestamp":"2026-06-16T19:37:49.226666Z","id":"CVE-2025-40271","options":[{"Exploitation":"none"},{"Automatable":"no"},{"Technical Impact":"partial"}],"role":"CISA Coordinator","version":"2.0.3"}}}],"providerMetadata":{"shortName":"CISA-ADP","orgId":"134c704f-9b21-4f2e-91b3-4a467353bcc0","dateUpdated":"2026-06-16T19:37:59.970Z"}}]}}}