From: Rajasi Mandal <[email protected]>
Every other tcon reference-count update takes tcon->tc_lock:
cifs_put_tcon(), the reconnect/mount paths in connect.c, misc.c,
smb2misc.c, smb2ops.c, smb2pdu.c, smb2transport.c, cifs_swn.c, and the
two other cached-dir sites (invalidate_all_cached_dirs_sb() and
cfids_laundromat_worker()). cached_dir_lease_break() is the sole
exception: it bumps tcon->tc_count with only cfids->cfid_list_lock
held.
A lease break can therefore race another tc_count writer (e.g. a
concurrent put/get) and lose an update, which under-counts the tcon and
risks an early teardown / use-after-free, or over-counts and leaks it.
Take tcon->tc_lock across the increment and its tracepoint, matching
every other site. The lock is nested inside cfid_list_lock; that
ordering is consistent with the rest of the file (tc_lock is a leaf
lock taken only for brief tcon field updates, and no path acquires
cfid_list_lock while holding tc_lock), so it introduces no new
ordering.
Signed-off-by: Rajasi Mandal <[email protected]>
---
fs/smb/client/cached_dir.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index f85d2d1dbbe3..c9b6eb56b37b 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -766,9 +766,11 @@ bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
cfid->on_list = false;
cfids->num_entries--;
+ spin_lock(&tcon->tc_lock);
++tcon->tc_count;
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
netfs_trace_tcon_ref_get_cached_lease_break);
+ spin_unlock(&tcon->tc_lock);
queue_work(cfid_put_wq, &cfid->put_work);
spin_unlock(&cfids->cfid_list_lock);
return true;
--
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.