]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: client: set correct d_type for reparse points under DFS mounts
authorPaulo Alcantara <pc@manguebit.com>
Fri, 2 Feb 2024 15:38:24 +0000 (12:38 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2024 12:34:56 +0000 (13:34 +0100)
[ Upstream commit 55c7788c37242702868bfac7861cdf0c358d6c3d ]

Send query dir requests with an info level of
SMB_FIND_FILE_FULL_DIRECTORY_INFO rather than
SMB_FIND_FILE_DIRECTORY_INFO when the client is generating its own
inode numbers (e.g. noserverino) so that reparse tags still
can be parsed directly from the responses, but server won't
send UniqueId (server inode number)

Signed-off-by: Paulo Alcantara <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/client/readdir.c
fs/smb/client/smb2pdu.c

index d30ea2005eb361a9d9af8ba39568d4168409a3ee..e23cd216bffbe04a70d132d963aaf15f7d15ac8b 100644 (file)
@@ -299,14 +299,16 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
 }
 
 static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
-                                      SEARCH_ID_FULL_DIR_INFO *info,
+                                      const void *info,
                                       struct cifs_sb_info *cifs_sb)
 {
+       const FILE_FULL_DIRECTORY_INFO *di = info;
+
        __dir_info_to_fattr(fattr, info);
 
-       /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */
+       /* See MS-FSCC 2.4.14, 2.4.19 */
        if (fattr->cf_cifsattrs & ATTR_REPARSE)
-               fattr->cf_cifstag = le32_to_cpu(info->EaSize);
+               fattr->cf_cifstag = le32_to_cpu(di->EaSize);
        cifs_fill_common_info(fattr, cifs_sb);
 }
 
@@ -420,7 +422,7 @@ ffirst_retry:
        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
        } else /* not srvinos - BB fixme add check for backlevel? */ {
-               cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+               cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
        }
 
        search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
@@ -1014,10 +1016,9 @@ static int cifs_filldir(char *find_entry, struct file *file,
                                       (FIND_FILE_STANDARD_INFO *)find_entry,
                                       cifs_sb);
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
        case SMB_FIND_FILE_ID_FULL_DIR_INFO:
-               cifs_fulldir_info_to_fattr(&fattr,
-                                          (SEARCH_ID_FULL_DIR_INFO *)find_entry,
-                                          cifs_sb);
+               cifs_fulldir_info_to_fattr(&fattr, find_entry, cifs_sb);
                break;
        default:
                cifs_dir_info_to_fattr(&fattr,
index 97fc2f85b429dfcf8d21f594005e7a9ca5115d14..9d34a55fdb5e4140e5fb62f6b63a50e8a5218b2a 100644 (file)
@@ -5092,6 +5092,9 @@ int SMB2_query_directory_init(const unsigned int xid,
        case SMB_FIND_FILE_POSIX_INFO:
                req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO;
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               req->FileInformationClass = FILE_FULL_DIRECTORY_INFORMATION;
+               break;
        default:
                cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
                        info_level);
@@ -5161,6 +5164,9 @@ smb2_parse_query_directory(struct cifs_tcon *tcon,
                /* note that posix payload are variable size */
                info_buf_size = sizeof(struct smb2_posix_info);
                break;
+       case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+               info_buf_size = sizeof(FILE_FULL_DIRECTORY_INFO);
+               break;
        default:
                cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
                         srch_inf->info_level);