From: Paulo Alcantara Date: Fri, 17 Apr 2026 00:15:50 +0000 (-0300) Subject: smb: client: fix dir separator in SMB1 UNIX mounts X-Git-Tag: v7.1-rc1~35^2~17 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=c4d3fc5844d685441befd0caaab648321013cdfd;p=thirdparty%2Flinux.git smb: client: fix dir separator in SMB1 UNIX mounts When calling cifs_mount_get_tcon() with SMB1 UNIX mounts, @cifs_sb->mnt_cifs_flags needs to be read or updated only after calling reset_cifs_unix_caps(), otherwise it might end up with missing CIFS_MOUNT_POSIXACL and CIFS_MOUNT_POSIX_PATHS bits. This fixes the wrong dir separator used in paths caused by the missing CIFS_MOUNT_POSIX_PATHS bit in cifs_sb_info::mnt_cifs_flags. Reported-by: "Kris Karas (Bug Reporting)" Closes: https://lore.kernel.org/r/f758f4ff-4d54-4244-931d-38f469c3ff14@moonlit-rail.com Fixes: 4fc3a433c139 ("smb: client: use atomic_t for mnt_cifs_flags") Signed-off-by: Paulo Alcantara (Red Hat) Cc: David Howells Cc: linux-cifs@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Steve French --- diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index ca1bc67eb23be..dcde25da468df 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -3609,7 +3609,6 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx) server = mnt_ctx->server; ctx = mnt_ctx->fs_ctx; cifs_sb = mnt_ctx->cifs_sb; - sbflags = cifs_sb_flags(cifs_sb); /* search for existing tcon to this server share */ tcon = cifs_get_tcon(mnt_ctx->ses, ctx); @@ -3624,9 +3623,10 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx) * path (i.e., do not remap / and \ and do not map any special characters) */ if (tcon->posix_extensions) { - sbflags |= CIFS_MOUNT_POSIX_PATHS; - sbflags &= ~(CIFS_MOUNT_MAP_SFM_CHR | - CIFS_MOUNT_MAP_SPECIAL_CHR); + atomic_or(CIFS_MOUNT_POSIX_PATHS, &cifs_sb->mnt_cifs_flags); + atomic_andnot(CIFS_MOUNT_MAP_SFM_CHR | + CIFS_MOUNT_MAP_SPECIAL_CHR, + &cifs_sb->mnt_cifs_flags); } #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY @@ -3650,6 +3650,7 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx) #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ tcon->unix_ext = 0; /* server does not support them */ + sbflags = cifs_sb_flags(cifs_sb); /* do not care if a following call succeed - informational */ if (!tcon->pipe && server->ops->qfs_tcon) { server->ops->qfs_tcon(mnt_ctx->xid, tcon, cifs_sb); @@ -3674,7 +3675,6 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx) out: mnt_ctx->tcon = tcon; - atomic_set(&cifs_sb->mnt_cifs_flags, sbflags); return rc; } diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 9694117050a6c..e198e3dda9177 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -49,7 +49,6 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, if (!CIFSSMBQFSUnixInfo(xid, tcon)) { __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - unsigned int sbflags; cifs_dbg(FYI, "unix caps which server supports %lld\n", cap); /* @@ -76,29 +75,27 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) cifs_dbg(VFS, "per-share encryption not supported yet\n"); - if (cifs_sb) - sbflags = cifs_sb_flags(cifs_sb); - cap &= CIFS_UNIX_CAP_MASK; if (ctx && ctx->no_psx_acl) cap &= ~CIFS_UNIX_POSIX_ACL_CAP; else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { cifs_dbg(FYI, "negotiated posix acl support\n"); - if (cifs_sb) - sbflags |= CIFS_MOUNT_POSIXACL; + if (cifs_sb) { + atomic_or(CIFS_MOUNT_POSIXACL, + &cifs_sb->mnt_cifs_flags); + } } if (ctx && ctx->posix_paths == 0) cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { cifs_dbg(FYI, "negotiate posix pathnames\n"); - if (cifs_sb) - sbflags |= CIFS_MOUNT_POSIX_PATHS; + if (cifs_sb) { + atomic_or(CIFS_MOUNT_POSIX_PATHS, + &cifs_sb->mnt_cifs_flags); + } } - if (cifs_sb) - atomic_set(&cifs_sb->mnt_cifs_flags, sbflags); - cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap); #ifdef CONFIG_CIFS_DEBUG2 if (cap & CIFS_UNIX_FCNTL_CAP)