fs/cifs: make share unaccessible at root level mountable
if, when mounting //HOST/share/sub/dir/foo we can query /sub/dir/foo but not any of the path components above: - store the /sub/dir/foo prefix in the cifs super_block info - in the superblock, set root dentry to the subpath dentry (instead of the share root) - set a flag in the superblock to remember it - use prefixpath when building path from a dentry fixes bso#8950 Signed-off-by: Aurelien Aptel <aaptel@suse.com> CC: Stable <stable@vger.kernel.org> Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:

committed by
Steve French

parent
bd975d1eea
commit
a6b5058faf
@@ -3485,6 +3485,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
|
||||
return volume_info;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
|
||||
unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
char *full_path)
|
||||
{
|
||||
int rc;
|
||||
char *s;
|
||||
char sep, tmp;
|
||||
|
||||
sep = CIFS_DIR_SEP(cifs_sb);
|
||||
s = full_path;
|
||||
|
||||
rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
|
||||
while (rc == 0) {
|
||||
/* skip separators */
|
||||
while (*s == sep)
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
/* next separator */
|
||||
while (*s && *s != sep)
|
||||
s++;
|
||||
|
||||
/*
|
||||
* temporarily null-terminate the path at the end of
|
||||
* the current component
|
||||
*/
|
||||
tmp = *s;
|
||||
*s = 0;
|
||||
rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
|
||||
full_path);
|
||||
*s = tmp;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
|
||||
{
|
||||
@@ -3622,6 +3660,16 @@ remote_path_check:
|
||||
kfree(full_path);
|
||||
goto mount_fail_check;
|
||||
}
|
||||
|
||||
rc = cifs_are_all_path_components_accessible(server,
|
||||
xid, tcon, cifs_sb,
|
||||
full_path);
|
||||
if (rc != 0) {
|
||||
cifs_dbg(VFS, "cannot query dirs between root and final path, "
|
||||
"enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
rc = 0;
|
||||
}
|
||||
kfree(full_path);
|
||||
}
|
||||
|
||||
@@ -3891,6 +3939,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
|
||||
|
||||
bdi_destroy(&cifs_sb->bdi);
|
||||
kfree(cifs_sb->mountdata);
|
||||
kfree(cifs_sb->prepath);
|
||||
call_rcu(&cifs_sb->rcu, delayed_free);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user