summaryrefslogtreecommitdiff
path: root/fs/smb/client
diff options
context:
space:
mode:
authorHenrique Carvalho <henrique.carvalho@suse.com>2026-01-27 13:01:28 -0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-02-16 10:19:40 +0100
commitc4b9edd55987384a1f201d3d07ff71e448d79c1b (patch)
tree73202ddf9f02bf512edbe1bf3b54de5ae323ea79 /fs/smb/client
parent1658b66fed206b5417cc301d67e888fd67dd130a (diff)
smb: client: split cached_fid bitfields to avoid shared-byte RMW races
commit ec306600d5ba7148c9dbf8f5a8f1f5c1a044a241 upstream. is_open, has_lease and on_list are stored in the same bitfield byte in struct cached_fid but are updated in different code paths that may run concurrently. Bitfield assignments generate byte read–modify–write operations (e.g. `orb $mask, addr` on x86_64), so updating one flag can restore stale values of the others. A possible interleaving is: CPU1: load old byte (has_lease=1, on_list=1) CPU2: clear both flags (store 0) CPU1: RMW store (old | IS_OPEN) -> reintroduces cleared bits To avoid this class of races, convert these flags to separate bool fields. Cc: stable@vger.kernel.org Fixes: ebe98f1447bbc ("cifs: enable caching of directories for which a lease is held") 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>
Diffstat (limited to 'fs/smb/client')
-rw-r--r--fs/smb/client/cached_dir.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index 1e383db7c337..5091bf45345e 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -36,10 +36,10 @@ struct cached_fid {
struct list_head entry;
struct cached_fids *cfids;
const char *path;
- bool has_lease:1;
- bool is_open:1;
- bool on_list:1;
- bool file_all_info_is_valid:1;
+ bool has_lease;
+ bool is_open;
+ bool on_list;
+ bool file_all_info_is_valid;
unsigned long time; /* jiffies of when lease was taken */
unsigned long last_access_time; /* jiffies of when last accessed */
struct kref refcount;