]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
authorChuck Lever <chuck.lever@oracle.com>
Thu, 7 May 2026 08:53:08 +0000 (04:53 -0400)
committerChristian Brauner <brauner@kernel.org>
Mon, 11 May 2026 14:50:30 +0000 (16:50 +0200)
FS_ATTRIBUTE_INFORMATION responses have always reported
FILE_CASE_SENSITIVE_SEARCH and FILE_CASE_PRESERVED_NAMES
unconditionally. Case-insensitive filesystems like exFAT, and
casefolded directories on ext4 or f2fs, have no way to signal
their actual semantics to SMB clients.

Now that filesystems expose case behavior through ->fileattr_get,
query it via vfs_fileattr_get() and translate the FS_XFLAG_CASEFOLD
and FS_XFLAG_CASENONPRESERVING flags into the corresponding SMB
attributes. Filesystems without ->fileattr_get continue reporting
default POSIX behavior (case-sensitive, case-preserving).

SMB's FS_ATTRIBUTE_INFORMATION reports per-share attributes from
the share root, not per-file. Shares mixing casefold and
non-casefold directories report the root directory's behavior.

Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://patch.msgid.link/20260507-case-sensitivity-v14-15-e62cc8200435@oracle.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/smb/server/smb2pdu.c

index 21825a69c29a7e635bea001b3e677e8a4b79489b..0f96eb878f29e0fe31c89fe96523baa48bd2761b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/falloc.h>
 #include <linux/mount.h>
 #include <linux/filelock.h>
+#include <linux/fileattr.h>
 
 #include "glob.h"
 #include "smbfsctl.h"
@@ -5542,16 +5543,33 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
        case FS_ATTRIBUTE_INFORMATION:
        {
                FILE_SYSTEM_ATTRIBUTE_INFO *info;
+               struct file_kattr fa = {};
                size_t sz;
+               u32 attrs;
+               int err;
 
                info = (FILE_SYSTEM_ATTRIBUTE_INFO *)rsp->Buffer;
-               info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
-                                              FILE_PERSISTENT_ACLS |
-                                              FILE_UNICODE_ON_DISK |
-                                              FILE_CASE_PRESERVED_NAMES |
-                                              FILE_CASE_SENSITIVE_SEARCH |
-                                              FILE_SUPPORTS_BLOCK_REFCOUNTING);
+               attrs = FILE_SUPPORTS_OBJECT_IDS |
+                       FILE_PERSISTENT_ACLS |
+                       FILE_UNICODE_ON_DISK |
+                       FILE_SUPPORTS_BLOCK_REFCOUNTING;
+
+               err = vfs_fileattr_get(path.dentry, &fa);
+               /*
+                * -EINVAL, -EOPNOTSUPP: ntfs-3g and other FUSE
+                * filesystems that lack FS_IOC_FSGETXATTR support.
+                */
+               if (err && err != -ENOIOCTLCMD && err != -ENOTTY &&
+                   err != -EINVAL && err != -EOPNOTSUPP) {
+                       path_put(&path);
+                       return err;
+               }
+               if (!(fa.fsx_xflags & FS_XFLAG_CASEFOLD))
+                       attrs |= FILE_CASE_SENSITIVE_SEARCH;
+               if (!(fa.fsx_xflags & FS_XFLAG_CASENONPRESERVING))
+                       attrs |= FILE_CASE_PRESERVED_NAMES;
 
+               info->Attributes = cpu_to_le32(attrs);
                info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
 
                if (test_share_config_flag(work->tcon->share_conf,