Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

smb: client: use actual path when queryfs

Due to server permission control, the client does not have access to
the shared root directory, but can access subdirectories normally, so
users usually mount the shared subdirectories directly. In this case,
queryfs should use the actual path instead of the root directory to
avoid the call returning an error (EACCES).

Signed-off-by: wangrong <wangrong@uniontech.com>
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Cc: stable@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

wangrong and committed by
Steve French
a421e3fe c9432ad5

+26 -10
+12 -1
fs/smb/client/cifsfs.c
··· 313 313 struct TCP_Server_Info *server = tcon->ses->server; 314 314 unsigned int xid; 315 315 int rc = 0; 316 + const char *full_path; 317 + void *page; 316 318 317 319 xid = get_xid(); 320 + page = alloc_dentry_path(); 321 + 322 + full_path = build_path_from_dentry(dentry, page); 323 + if (IS_ERR(full_path)) { 324 + rc = PTR_ERR(full_path); 325 + goto statfs_out; 326 + } 318 327 319 328 if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0) 320 329 buf->f_namelen = ··· 339 330 buf->f_ffree = 0; /* unlimited */ 340 331 341 332 if (server->ops->queryfs) 342 - rc = server->ops->queryfs(xid, tcon, cifs_sb, buf); 333 + rc = server->ops->queryfs(xid, tcon, full_path, cifs_sb, buf); 343 334 335 + statfs_out: 336 + free_dentry_path(page); 344 337 free_xid(xid); 345 338 return rc; 346 339 }
+1 -1
fs/smb/client/cifsglob.h
··· 481 481 __u16 net_fid, struct cifsInodeInfo *cifs_inode); 482 482 /* query remote filesystem */ 483 483 int (*queryfs)(const unsigned int, struct cifs_tcon *, 484 - struct cifs_sb_info *, struct kstatfs *); 484 + const char *, struct cifs_sb_info *, struct kstatfs *); 485 485 /* send mandatory brlock to the server */ 486 486 int (*mand_lock)(const unsigned int, struct cifsFileInfo *, __u64, 487 487 __u64, __u32, int, int, bool);
+1 -1
fs/smb/client/smb1ops.c
··· 909 909 910 910 static int 911 911 cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon, 912 - struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 912 + const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 913 913 { 914 914 int rc = -EOPNOTSUPP; 915 915
+12 -7
fs/smb/client/smb2ops.c
··· 2838 2838 2839 2839 static int 2840 2840 smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, 2841 - struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 2841 + const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 2842 2842 { 2843 2843 struct smb2_query_info_rsp *rsp; 2844 2844 struct smb2_fs_full_size_info *info = NULL; ··· 2847 2847 int rc; 2848 2848 2849 2849 2850 - rc = smb2_query_info_compound(xid, tcon, "", 2850 + rc = smb2_query_info_compound(xid, tcon, path, 2851 2851 FILE_READ_ATTRIBUTES, 2852 2852 FS_FULL_SIZE_INFORMATION, 2853 2853 SMB2_O_INFO_FILESYSTEM, ··· 2875 2875 2876 2876 static int 2877 2877 smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon, 2878 - struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 2878 + const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 2879 2879 { 2880 2880 int rc; 2881 - __le16 srch_path = 0; /* Null - open root of share */ 2881 + __le16 *utf16_path = NULL; 2882 2882 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 2883 2883 struct cifs_open_parms oparms; 2884 2884 struct cifs_fid fid; 2885 2885 2886 2886 if (!tcon->posix_extensions) 2887 - return smb2_queryfs(xid, tcon, cifs_sb, buf); 2887 + return smb2_queryfs(xid, tcon, path, cifs_sb, buf); 2888 2888 2889 2889 oparms = (struct cifs_open_parms) { 2890 2890 .tcon = tcon, 2891 - .path = "", 2891 + .path = path, 2892 2892 .desired_access = FILE_READ_ATTRIBUTES, 2893 2893 .disposition = FILE_OPEN, 2894 2894 .create_options = cifs_create_options(cifs_sb, 0), 2895 2895 .fid = &fid, 2896 2896 }; 2897 2897 2898 - rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, 2898 + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 2899 + if (utf16_path == NULL) 2900 + return -ENOMEM; 2901 + 2902 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, 2899 2903 NULL, NULL); 2904 + kfree(utf16_path); 2900 2905 if (rc) 2901 2906 return rc; 2902 2907