FAILED: patch "[PATCH] smb: client: fix fattr leaking on wsl_to_fattr() failure" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x e1253a82bb4c0fed6706a5839fc8b6e01be1abe2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092250-moneywise-parameter-6a1d@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e1253a82bb4c0fed6706a5839fc8b6e01be1abe2 Mon Sep 17 00:00:00 2001
From: Paulo Alcantara <[email protected]>
Date: Sun, 13 Sep 2026 21:15:41 -0300
Subject: [PATCH] smb: client: fix fattr leaking on wsl_to_fattr() failure
wsl_to_fattr() mutates fattr fields as it parses each WSL EA. If validation later fails, the function returns false with partially mutated fattr fields that callers do not reset.
Fix this by parsing into local variables and only committing them to fattr on success.
fs/smb/client/reparse.c +19 -15
@@ -1149,29 +1149,30 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data, u32 tag, struct cifs_fattr *fattr) {unsigned int sbflags =cifs_sb_flags (cifs_sb); +kuid_t uid = cifs_sb->ctx->linux_uid; +kgid_t gid = cifs_sb->ctx->linux_gid;struct smb2_file_full_ea_info *ea;bool have_xattr_dev = false; +dev_t rdev =0 ; +umode_t mode;u32 next =0 ; - fattr->cf_uid = cifs_sb->ctx->linux_uid; - fattr->cf_gid = cifs_sb->ctx->linux_gid; - - fattr->cf_mode &= ~S_IFMT ; + mode = fattr->cf_mode & ~S_IFMT ;switch (tag) {case IO_REPARSE_TAG_LX_SYMLINK : - fattr->cf_mode |=S_IFLNK ; + mode |=S_IFLNK ;break ;case IO_REPARSE_TAG_LX_FIFO : - fattr->cf_mode |=S_IFIFO ; + mode |=S_IFIFO ;break ;case IO_REPARSE_TAG_AF_UNIX : - fattr->cf_mode |=S_IFSOCK ; + mode |=S_IFSOCK ;break ;case IO_REPARSE_TAG_LX_CHR : - fattr->cf_mode |=S_IFCHR ; + mode |=S_IFCHR ;break ;case IO_REPARSE_TAG_LX_BLK : - fattr->cf_mode |=S_IFBLK ; + mode |=S_IFBLK ;break ; }
@@ -1195,26 +1196,29 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data,if (!strncmp (name,SMB2_WSL_XATTR_UID , nlen)) {if (!(sbflags &CIFS_MOUNT_OVERR_UID )) - fattr->cf_uid =wsl_make_kuid (cifs_sb, v); + uid =wsl_make_kuid (cifs_sb, v); }else if (!strncmp (name,SMB2_WSL_XATTR_GID , nlen)) {if (!(sbflags &CIFS_MOUNT_OVERR_GID )) - fattr->cf_gid =wsl_make_kgid (cifs_sb, v); + gid =wsl_make_kgid (cifs_sb, v); }else if (!strncmp (name,SMB2_WSL_XATTR_MODE , nlen)) {/* File type in reparse point tag and in xattr mode must match. */ -if (S_DT (fattr->cf_mode) !=S_DT (get_unaligned_le32 (v))) +if (S_DT (mode) !=S_DT (get_unaligned_le32 (v)))return false; - fattr->cf_mode = (umode_t )get_unaligned_le32 (v); + mode =get_unaligned_le32 (v); }else if (!strncmp (name,SMB2_WSL_XATTR_DEV , nlen)) { - fattr->cf_rdev =reparse_mkdev (v); + rdev =reparse_mkdev (v); have_xattr_dev = true; } }while (next); out: -/* Major and minor numbers for char and block devices are mandatory. */ if (!have_xattr_dev && (tag ==IO_REPARSE_TAG_LX_CHR || tag ==IO_REPARSE_TAG_LX_BLK ))return false; + fattr->cf_uid = uid; + fattr->cf_gid = gid; + fattr->cf_mode = mode; + fattr->cf_rdev = rdev;return true; }
Sasha Levin
maintainerPATCH 1/2 smb: client: use atomic_t for mnt_cifs_flags
From: Paulo Alcantara <[email protected]>
[ Upstream commit 4fc3a433c13944ee5766ec5b9bf6f1eb4d29b880 ]
Use atomic_t for cifs_sb_info::mnt_cifs_flags as it's currently accessed locklessly and may be changed concurrently in mount/remount and reconnect paths.
Stable dependency adaptation for e1253a82bb4c0fed6706a5839fc8b6e01be1abe2:
Retain the cifs_sb_flags interface needed by the WSL parser, implemented as a READ_ONCE macro over the existing unsigned mount flags. Drop the client-wide atomic_t conversion, generic CIFS_SB helpers, and unrelated symlink/refactoring hunks that depend on newer SMB client code. This stable adaptation does not implement the upstream atomic write changes. No functions are added.
Prepare the existing wsl_to_fattr implementation to match the target's
preimage: include the UID/GID defaults and forceuid/forcegid checks from cd2b2b57921d4, file-type clearing from fa7a2cfcf1e61, and unaligned WSL reads from e1aeaf79dea51. Use asm/unaligned.h as required by 6.6. Keep the target's transactional fattr update for the target commit itself.
The target patch applies unchanged after this dependency adaptation.
[ sashal: Reduced backport -- upstream 4fc3a433c1394 touches 27 file(s), this
backport carries 3. Not backported here:
fs/smb/client/cached_dir.c
fs/smb/client/cifsacl.c
fs/smb/client/cifsfs.c
fs/smb/client/cifs_fs_sb.h
fs/smb/client/cifs_ioctl.h
fs/smb/client/cifs_unicode.c
fs/smb/client/cifs_unicode.h
fs/smb/client/connect.c
... and 16 more
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: e1253a82bb4c ("smb: client: fix fattr leaking on wsl_to_fattr() failure")
--- fs/smb/client/cifsglob.h | 3 +++ fs/smb/client/reparse.c | 21 ++++++++++++++------- fs/smb/client/reparse.h | 11 ++++++----- 3 files changed, 23 insertions(+), 12 deletions(-)
fs/smb/client/cifsglob.h +3 -0
@@ -1603,6 +1603,9 @@ CIFS_FILE_SB(struct file *file)return CIFS_SB (file_inode (file)->i_sb); } +/* Mount and reconnect paths may update these flags concurrently. */ +#define cifs_sb_flags (cifs_sb) READ_ONCE((cifs_sb)->mnt_cifs_flags) +static inline char CIFS_DIR_SEP (const struct cifs_sb_info *cifs_sb) {if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_POSIX_PATHS )
fs/smb/client/reparse.c +14 -7
@@ -678,10 +678,15 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data,struct cifs_sb_info *cifs_sb, u32 tag, struct cifs_fattr *fattr) { + unsigned int sbflags = cifs_sb_flags(cifs_sb);struct smb2_file_full_ea_info *ea;bool have_xattr_dev = false;u32 next =0 ; + fattr->cf_uid = cifs_sb->ctx->linux_uid; + fattr->cf_gid = cifs_sb->ctx->linux_gid; + + fattr->cf_mode &= ~S_IFMT ;switch (tag) {case IO_REPARSE_TAG_LX_SYMLINK : fattr->cf_mode |=S_IFLNK ;
@@ -718,15 +723,17 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data, nlen = ea->ea_name_length; v = (void *)((u8 *)ea->ea_data + ea->ea_name_length +1 ); -if (!strncmp (name,SMB2_WSL_XATTR_UID , nlen)) - fattr->cf_uid =wsl_make_kuid (cifs_sb, v); -else if (!strncmp (name,SMB2_WSL_XATTR_GID , nlen)) - fattr->cf_gid =wsl_make_kgid (cifs_sb, v); -else if (!strncmp (name,SMB2_WSL_XATTR_MODE , nlen)) { +if (!strncmp (name,SMB2_WSL_XATTR_UID , nlen)) { +if (!(sbflags &CIFS_MOUNT_OVERR_UID )) + fattr->cf_uid =wsl_make_kuid (cifs_sb, v); + }else if (!strncmp (name,SMB2_WSL_XATTR_GID , nlen)) { +if (!(sbflags &CIFS_MOUNT_OVERR_GID )) + fattr->cf_gid =wsl_make_kgid (cifs_sb, v); + }else if (!strncmp (name,SMB2_WSL_XATTR_MODE , nlen)) {/* File type in reparse point tag and in xattr mode must match. */ -if (S_DT (fattr->cf_mode) !=S_DT (le32_to_cpu (*(__le32 *)v))) +if (S_DT (fattr->cf_mode) !=S_DT (get_unaligned_le32 (v)))return false; - fattr->cf_mode = (umode_t )le32_to_cpu (*(__le32 *)v); + fattr->cf_mode = (umode_t )get_unaligned_le32 (v); }else if (!strncmp (name,SMB2_WSL_XATTR_DEV , nlen)) { fattr->cf_rdev =reparse_mkdev (v); have_xattr_dev = true;
fs/smb/client/reparse.h +6 -5
@@ -9,6 +9,7 @@#include <linux/fs.h> #include <linux/stat.h> #include <linux/uidgid.h> +#include <asm/unaligned.h> #include "fs_context.h" #include "cifsglob.h"
@@ -22,7 +23,7 @@static inline dev_t reparse_mkdev (void *ptr) { -u64 v =le64_to_cpu (*(__le64 *)ptr); +u64 v =get_unaligned_le64 (ptr);return MKDEV (v &0xffffffff , v >>32 ); }
@@ -30,9 +31,9 @@ static inline dev_t reparse_mkdev(void *ptr)static inline kuid_t wsl_make_kuid (struct cifs_sb_info *cifs_sb,void *ptr) { -u32 uid =le32_to_cpu (*(__le32 *)ptr); +u32 uid =get_unaligned_le32 (ptr); -if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID ) +if (cifs_sb_flags (cifs_sb) &CIFS_MOUNT_OVERR_UID )return cifs_sb->ctx->linux_uid;return make_kuid (current_user_ns (), uid); }
@@ -40,9 +41,9 @@ static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,static inline kgid_t wsl_make_kgid (struct cifs_sb_info *cifs_sb,void *ptr) { -u32 gid =le32_to_cpu (*(__le32 *)ptr); +u32 gid =get_unaligned_le32 (ptr); -if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID ) +if (cifs_sb_flags (cifs_sb) &CIFS_MOUNT_OVERR_GID )return cifs_sb->ctx->linux_gid;return make_kgid (current_user_ns (), gid); }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 smb: client: fix fattr leaking on wsl_to_fattr() failure
From: Paulo Alcantara <[email protected]>
[ Upstream commit e1253a82bb4c0fed6706a5839fc8b6e01be1abe2 ]
wsl_to_fattr() mutates fattr fields as it parses each WSL EA. If validation later fails, the function returns false with partially mutated fattr fields that callers do not reset.
Fix this by parsing into local variables and only committing them to fattr on success.
--- fs/smb/client/reparse.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-)
fs/smb/client/reparse.c +19 -15
@@ -679,29 +679,30 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data, u32 tag, struct cifs_fattr *fattr) {unsigned int sbflags =cifs_sb_flags (cifs_sb); +kuid_t uid = cifs_sb->ctx->linux_uid; +kgid_t gid = cifs_sb->ctx->linux_gid;struct smb2_file_full_ea_info *ea;bool have_xattr_dev = false; +dev_t rdev =0 ; +umode_t mode;u32 next =0 ; - fattr->cf_uid = cifs_sb->ctx->linux_uid; - fattr->cf_gid = cifs_sb->ctx->linux_gid; - - fattr->cf_mode &= ~S_IFMT ; + mode = fattr->cf_mode & ~S_IFMT ;switch (tag) {case IO_REPARSE_TAG_LX_SYMLINK : - fattr->cf_mode |=S_IFLNK ; + mode |=S_IFLNK ;break ;case IO_REPARSE_TAG_LX_FIFO : - fattr->cf_mode |=S_IFIFO ; + mode |=S_IFIFO ;break ;case IO_REPARSE_TAG_AF_UNIX : - fattr->cf_mode |=S_IFSOCK ; + mode |=S_IFSOCK ;break ;case IO_REPARSE_TAG_LX_CHR : - fattr->cf_mode |=S_IFCHR ; + mode |=S_IFCHR ;break ;case IO_REPARSE_TAG_LX_BLK : - fattr->cf_mode |=S_IFBLK ; + mode |=S_IFBLK ;break ; }
@@ -725,26 +726,29 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data,if (!strncmp (name,SMB2_WSL_XATTR_UID , nlen)) {if (!(sbflags &CIFS_MOUNT_OVERR_UID )) - fattr->cf_uid =wsl_make_kuid (cifs_sb, v); + uid =wsl_make_kuid (cifs_sb, v); }else if (!strncmp (name,SMB2_WSL_XATTR_GID , nlen)) {if (!(sbflags &CIFS_MOUNT_OVERR_GID )) - fattr->cf_gid =wsl_make_kgid (cifs_sb, v); + gid =wsl_make_kgid (cifs_sb, v); }else if (!strncmp (name,SMB2_WSL_XATTR_MODE , nlen)) {/* File type in reparse point tag and in xattr mode must match. */ -if (S_DT (fattr->cf_mode) !=S_DT (get_unaligned_le32 (v))) +if (S_DT (mode) !=S_DT (get_unaligned_le32 (v)))return false; - fattr->cf_mode = (umode_t )get_unaligned_le32 (v); + mode =get_unaligned_le32 (v); }else if (!strncmp (name,SMB2_WSL_XATTR_DEV , nlen)) { - fattr->cf_rdev =reparse_mkdev (v); + rdev =reparse_mkdev (v); have_xattr_dev = true; } }while (next); out: -/* Major and minor numbers for char and block devices are mandatory. */ if (!have_xattr_dev && (tag ==IO_REPARSE_TAG_LX_CHR || tag ==IO_REPARSE_TAG_LX_BLK ))return false; + fattr->cf_uid = uid; + fattr->cf_gid = gid; + fattr->cf_mode = mode; + fattr->cf_rdev = rdev;return true; }
Signature · 1 line
2.53.0