CVE-2026-64142
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
19/07/2026
Last modified:
30/07/2026
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
ksmbd: close durable scavenger races against m_fp_list lookups<br />
<br />
ksmbd_durable_scavenger() has two related races against any walker<br />
that iterates f_ci->m_fp_list, including ksmbd_lookup_fd_inode()<br />
(used by ksmbd_vfs_rename) and the share-mode checks in<br />
fs/smb/server/smb_common.c.<br />
<br />
(1) fp->node list-head reuse. Durable-preserved handles can remain<br />
linked on f_ci->m_fp_list after session teardown so share-mode checks<br />
still see them while the handle is reconnectable. The scavenger<br />
collected expired handles by adding fp->node to a local<br />
scavenger_list after removing them from the global durable idr.<br />
Because fp->node is the same list_head used by m_fp_list,<br />
list_add(&fp->node, &scavenger_list) overwrites the m_fp_list links<br />
and corrupts both lists. CONFIG_DEBUG_LIST can report this on the<br />
share-mode walk path.<br />
<br />
(2) Refcount race against m_fp_list walkers. The scavenger qualifies<br />
an expired durable handle with atomic_read(&fp->refcount) > 1 and<br />
fp->conn under global_ft.lock, removes fp from global_ft, then drops<br />
global_ft.lock before unlinking fp from m_fp_list and freeing it.<br />
During that gap fp is still linked on m_fp_list with f_state ==<br />
FP_INITED. ksmbd_lookup_fd_inode() under m_lock read calls<br />
ksmbd_fp_get() (atomic_inc_not_zero on refcount that is still 1) and<br />
takes a live reference; the scavenger then unlinks and frees fp<br />
while the holder owns a reference, leading to UAF on the holder&#39;s<br />
subsequent ksmbd_fd_put() and on any field reads performed by a<br />
concurrent share-mode walker that iterates m_fp_list without taking<br />
ksmbd_fp_get() (smb_check_perm_dleases-like paths).<br />
<br />
Fix both:<br />
<br />
* Stop reusing fp->node as a scavenger-private list node. Remove<br />
one expired handle from global_ft under global_ft.lock, take an<br />
explicit transient reference, drop the lock, unlink fp->node<br />
from m_fp_list under f_ci->m_lock, then drop both the durable<br />
lifetime and transient references with atomic_sub_and_test(2,<br />
&fp->refcount). If the scavenger is the last putter the close<br />
runs there; otherwise an in-flight holder that already raced<br />
through the m_fp_list lookup owns the final close via its<br />
ksmbd_fd_put() path. The one-at-a-time disposal can rescan the<br />
durable idr when multiple handles expire in the same pass, but<br />
durable scavenging is a background expiration path and the final<br />
full scan recomputes min_timeout before the next wait.<br />
<br />
* Clear fp->persistent_id inside __ksmbd_remove_durable_fd() right<br />
after idr_remove(), so a delayed final close from a holder that<br />
snatched fp does not re-issue idr_remove() on a persistent id<br />
that idr_alloc_cyclic() in ksmbd_open_durable_fd() may have<br />
already handed out to a brand-new durable handle.<br />
<br />
* Bypass the per-conn open_files_count decrement in<br />
__put_fd_final() when fp is detached from any session table<br />
(fp->conn cleared by session_fd_check() at durable preserve --<br />
paired with the volatile_id clear at unpublish, so checking<br />
fp->conn alone is sufficient). The walker that owns the final<br />
close runs from an unrelated work->conn whose<br />
stats.open_files_count never tracked this durable fp; without<br />
this guard the holder would underflow that unrelated counter.<br />
<br />
The two races are folded into one patch because patch (1) alone<br />
cleans up the corrupted list but leaves a deterministic UAF window<br />
for m_fp_list walkers that the transient-reference and<br />
persistent_id discipline in (2) close; bisecting onto an<br />
intermediate state would land on a UAF that pre-patch chaos merely<br />
made less reproducible.<br />
<br />
Validation:<br />
* CONFIG_DEBUG_LIST coverage for the list_head reuse path.<br />
* KASAN-enabled direct SMB2 durable-handle coverage that exercised<br />
ksmbd_durable_scavenger() and non-NULL ksmbd_lookup_fd_inode()<br />
returns while durable handles expired under concurrent rename<br />
lookups, with no KASAN, UAF, list-corruption, ODEBUG, or WARNING<br />
reports.<br />
---truncated---
Impact
Base Score 3.x
9.80
Severity 3.x
CRITICAL
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/1f8f3246d55f89350a1a67bdf3744b7241048e4e
- https://git.kernel.org/stable/c/3a436932eb397e909d0607d76a8325abd9d85a35
- https://git.kernel.org/stable/c/5da69a65b282d2276de22e5194ba0f88c836170c
- https://git.kernel.org/stable/c/95f072ef934ca00711d510676b8792cbf59a5aae
- https://git.kernel.org/stable/c/bf736184d063da1a552ffeff0481813599a182cc



