]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smb: client: fix dir separator in SMB1 UNIX mounts
authorPaulo Alcantara <pc@manguebit.org>
Fri, 17 Apr 2026 00:15:50 +0000 (21:15 -0300)
committerSteve French <stfrench@microsoft.com>
Fri, 17 Apr 2026 04:21:00 +0000 (23:21 -0500)
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)" <bugs-a21@moonlit-rail.com>
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) <pc@manguebit.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/connect.c
fs/smb/client/smb1ops.c

index ca1bc67eb23beaed5e9412d191b1e2f83b972330..dcde25da468dfb9fa3e89df5eb0bf5b420aa5480 100644 (file)
@@ -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;
 }
 
index 9694117050a6c7758d2d06f680f3a8cf660f6647..e198e3dda91772e52234b29931be3a69a1903e53 100644 (file)
@@ -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)