On 11. 11. 25, 1:46, Greg Kroah-Hartman wrote:
6.17-stable review patch. If anyone has any objections, please let me know.
From: Henrique Carvalho henrique.carvalho@suse.com
commit 734e99623c5b65bf2c03e35978a0b980ebc3c2f8 upstream.
find_or_create_cached_dir() could grab a new reference after kref_put() had seen the refcount drop to zero but before cfid_list_lock is acquired in smb2_close_cached_fid(), leading to use-after-free.
Switch to kref_put_lock() so cfid_release() is called with cfid_list_lock held, closing that gap.
Fixes: ebe98f1447bb ("cifs: enable caching of directories for which a lease is held") Cc: stable@vger.kernel.org Reported-by: Jay Shin jaeshin@redhat.com Reviewed-by: Paulo Alcantara (Red Hat) pc@manguebit.org Signed-off-by: Henrique Carvalho henrique.carvalho@suse.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
fs/smb/client/cached_dir.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
--- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -389,11 +389,11 @@ out: * lease. Release one here, and the second below. */ cfid->has_lease = false;
kref_put(&cfid->refcount, smb2_close_cached_fid);
} spin_unlock(&cfids->cfid_list_lock);close_cached_dir(cfid);
kref_put(&cfid->refcount, smb2_close_cached_fid);
} else { *ret_cfid = cfid; atomic_inc(&tcon->num_remote_opens);close_cached_dir(cfid);@@ -434,12 +434,14 @@ int open_cached_dir_by_dentry(struct cif static void smb2_close_cached_fid(struct kref *ref) +__releases(&cfid->cfids->cfid_list_lock) { struct cached_fid *cfid = container_of(ref, struct cached_fid, refcount); int rc;
- spin_lock(&cfid->cfids->cfid_list_lock);
- lockdep_assert_held(&cfid->cfids->cfid_list_lock);
This _backport_ (of a 6.18-rc5 commit) omits to change cfids_invalidation_worker() which was removed in 6.18-rc1 by: 7ae6152b7831 smb: client: remove cfids_invalidation_worker
This likely causes: https://bugzilla.suse.com/show_bug.cgi?id=1254096 BUG: workqueue leaked atomic, lock or RCU
Because cfids_invalidation_worker() still does: kref_put(&cfid->refcount, smb2_close_cached_fid); instead of now required kref_put_lock() aka: close_cached_dir(cfid);
thanks,