]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ksmbd: provide zero as a unique ID to the Mac client
authorNamjae Jeon <linkinjeon@kernel.org>
Wed, 21 May 2025 00:02:29 +0000 (09:02 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 27 May 2025 15:25:12 +0000 (10:25 -0500)
The Mac SMB client code seems to expect the on-disk file identifier
to have the semantics of HFS+ Catalog Node Identifier (CNID).
ksmbd provides the inode number as a unique ID to the client,
but in the case of subvolumes of btrfs, there are cases where different
files have the same inode number, so the mac smb client treats it
as an error. There is a report that a similar problem occurs
when the share is ZFS.
Returning UniqueId of zero will make the Mac client to stop using and
trusting the file id returned from the server.

Reported-by: Justin Turner Arthur <justinarthur@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/connection.h
fs/smb/server/smb2pdu.c
fs/smb/server/smb2pdu.h

index 14620e147dda570bc8d48b48250aad5438d5d75d..6efed923bd687dbe1882f956ce999090ada6797e 100644 (file)
@@ -108,6 +108,7 @@ struct ksmbd_conn {
        __le16                          signing_algorithm;
        bool                            binding;
        atomic_t                        refcnt;
+       bool                            is_aapl;
 };
 
 struct ksmbd_conn_ops {
index f2a2be8467c66900fbaa215ba8b954193b8d93ee..3a4bffe97b5435da63cc0391521e5507a0c99b4e 100644 (file)
@@ -3539,6 +3539,15 @@ int smb2_open(struct ksmbd_work *work)
                        ksmbd_debug(SMB, "get query on disk id context\n");
                        query_disk_id = 1;
                }
+
+               if (conn->is_aapl == false) {
+                       context = smb2_find_context_vals(req, SMB2_CREATE_AAPL, 4);
+                       if (IS_ERR(context)) {
+                               rc = PTR_ERR(context);
+                               goto err_out1;
+                       } else if (context)
+                               conn->is_aapl = true;
+               }
        }
 
        rc = ksmbd_vfs_getattr(&path, &stat);
@@ -3978,7 +3987,10 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
                if (dinfo->EaSize)
                        dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
                dinfo->Reserved = 0;
-               dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
+               if (conn->is_aapl)
+                       dinfo->UniqueId = 0;
+               else
+                       dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
                if (d_info->hide_dot_file && d_info->name[0] == '.')
                        dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
                memcpy(dinfo->FileName, conv_name, conv_len);
@@ -3995,7 +4007,10 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
                        smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
                if (fibdinfo->EaSize)
                        fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
-               fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
+               if (conn->is_aapl)
+                       fibdinfo->UniqueId = 0;
+               else
+                       fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
                fibdinfo->ShortNameLength = 0;
                fibdinfo->Reserved = 0;
                fibdinfo->Reserved2 = cpu_to_le16(0);
index 17a0b18a8406b3737521b44f82f67a35fd98f746..16ae8a10490beb5bc5865ad3cf1f8a5e6af4f0c4 100644 (file)
@@ -63,6 +63,9 @@ struct preauth_integrity_info {
 
 #define SMB2_SESSION_TIMEOUT           (10 * HZ)
 
+/* Apple Defined Contexts */
+#define SMB2_CREATE_AAPL               "AAPL"
+
 struct create_durable_req_v2 {
        struct create_context_hdr ccontext;
        __u8   Name[8];