CVE-2025-40271: fs/proc: fix uaf in proc_readdir_de()
In the Linux kernel, the following vulnerability has been resolved:
fs/proc: fix uaf in procreaddirde()
Pde is erased from subdir rbtree through rberase(), but not set the node to EMPTY, which may result in uaf access. We should use RBCLEARNODE() set the erased node to EMPTY, then pdesubdirnext() will return NULL to avoid uaf access.
We found an uaf issue while using stress-ng testing, need to run testcase getdent and tun in the same time. The steps of the issue is as follows:
1) use getdent to traverse dir /proc/pid/net/devsnmp6/, and current pde is tun3;
2) in the [time windows] unregister netdevice tun3 and tun2, and erase them from rbtree. erase tun3 first, and then erase tun2. the pde(tun2) will be released to slab;
3) continue to getdent process, then pdesubdirnext() will return pde(tun2) which is released, it will case uaf access.
CPU 0 | CPU 1 ------------------------------------------------------------------------- traverse dir /proc/pid/net/devsnmp6/ | unregisternetdevice(tun->dev) //tun3 tun2 sysgetdents64() | iteratedir() | procreaddir() | procreaddirde() | snmp6unregisterdev() pdeget(de); | procremove() readunlock(&procsubdirlock); | removeprocsubtree() | writelock(&procsubdirlock); [time window] | rberase(&root->subdirnode, &parent->subdir); | writeunlock(&procsubdirlock); readlock(&procsubdirlock); | next = pdesubdirnext(de); | pdeput(de); | de = next; //UAF |
rbtree of devsnmp6 | pde(tun3) / \ NULL pde(tun2)
Other sources
In the Linux kernel, the following vulnerability has been resolved:
fs/proc: fix uaf in procreaddirde()
Pde is erased from subdir rbtree through rberase(), but not set the node to EMPTY, which may result in uaf access. We should use RBCLEARNODE() set the erased node to EMPTY, then pdesubdirnext() will return NULL to avoid uaf access.
We found an uaf issue while using stress-ng testing, need to run testcase getdent and tun in the same time. The steps of the issue is as follows:
1) use getdent to traverse dir /proc/pid/net/devsnmp6/, and current pde is tun3;
2) in the [time windows] unregister netdevice tun3 and tun2, and erase them from rbtree. erase tun3 first, and then erase tun2. the pde(tun2) will be released to slab;
3) continue to getdent process, then pdesubdirnext() will return pde(tun2) which is released, it will case uaf access.
CPU 0 | CPU 1 ------------------------------------------------------------------------- traverse dir /proc/pid/net/devsnmp6/ | unregisternetdevice(tun-dev) //tun3 tun2 sysgetdents64() | iteratedir() | procreaddir() | procreaddirde() | snmp6unregisterdev() pdeget(de); | procremove() readunlock(&procsubdirlock); | removeprocsubtree() | writelock(&procsubdirlock); [time window] | rberase(&root-subdirnode, &parent-subdir); | writeunlock(&procsubdirlock); readlock(&procsubdirlock); | next = pdesubdirnext(de); | pdeput(de); | de = next; //UAF |
rbtree of devsnmp6 | pde(tun3) / \ NULL pde(tun2)
— IBM
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
In proc_readdir_de(), when removing a subdir node from the proc rbtree (via rb_erase(&root->subdir_node, &parent->subdir)), clear the node with RB_CLEAR_NODE() / set the erased node to EMPTY so pde_subdir_next() won’t return a pointer to an already-freed (UAF) pde entry.
Linux kernel procfs (proc_readdir_de / pde_subdir_next) RB_CLEAR_NODE = use RB_CLEAR_NODE() after rb_erase(&root->subdir_node, &parent->subdir) - Configuration
Ensure the rbtree erase/update path that removes pde entries from procfs subdirectories holds write_lock(&proc_subdir_lock) (rather than only read_lock) when erasing nodes, to avoid concurrent getdents traversal observing freed nodes.
Linux kernel procfs proc_remove / proc_readdir (proc_subdir_lock usage) proc_subdir_lock write locking around rbtree erase = write_lock/write_unlock - Compensating control
During remediation testing and/or vulnerability reproduction, avoid running getdents64 traversal of /proc/pid/net/dev_snmp6/ at the same time as unregistering netdevice tun2/tun3; unregister (erase) tun3 first, then tun2, within the relevant time window to reduce the likelihood of UAF during concurrent iteration.
Event History
Frequently Asked Questions
What is the severity of CVE-2025-40271?
CVE-2025-40271 has been classified as a medium severity vulnerability due to the potential for use-after-free access leading to memory corruption.
How do I fix CVE-2025-40271?
To fix CVE-2025-40271, update the Linux kernel to the latest stable version where the vulnerability has been patched.
Which versions of the Linux kernel are affected by CVE-2025-40271?
CVE-2025-40271 affects various versions of the Linux kernel prior to the release of the fix.
What does CVE-2025-40271 affect in the Linux kernel?
CVE-2025-40271 affects the proc_readdir_de() function, where a use-after-free condition can lead to exploitation.
Can CVE-2025-40271 lead to system compromise?
Yes, CVE-2025-40271 can potentially lead to system compromise through memory corruption exploits.