Commit ff2c54a0 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French

cifs: check all path components in resolved dfs target

Handle the case where a resolved target share is like
//server/users/dir, and the user "foo" has no read permission to
access the parent folder "users" but has access to the final path
component "dir".

is_path_remote() already implements that, so call it directly.
Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Cc: stable@vger.kernel.org # 5.11
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8513222b
...@@ -3289,56 +3289,27 @@ static void put_root_ses(struct cifs_ses *ses) ...@@ -3289,56 +3289,27 @@ static void put_root_ses(struct cifs_ses *ses)
cifs_put_smb_ses(ses); cifs_put_smb_ses(ses);
} }
/* Check if a path component is remote and then update @dfs_path accordingly */ /* Set up next dfs prefix path in @dfs_path */
static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, static int next_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
const unsigned int xid, struct TCP_Server_Info *server, const unsigned int xid, struct TCP_Server_Info *server,
struct cifs_tcon *tcon, char **dfs_path) struct cifs_tcon *tcon, char **dfs_path)
{ {
char *path, *s; char *path, *npath;
char sep = CIFS_DIR_SEP(cifs_sb), tmp; int added_treename = is_tcon_dfs(tcon);
char *npath; int rc;
int rc = 0;
int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
int skip = added_treename;
path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename); path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename);
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
/* rc = is_path_remote(cifs_sb, ctx, xid, server, tcon);
* Walk through the path components in @path and check if they're accessible. In case any of if (rc == -EREMOTE) {
* the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
* (NOT including the remaining components).
*/
s = path;
do {
/* skip separators */
while (*s && *s == sep)
s++;
if (!*s)
break;
/* next separator */
while (*s && *s != sep)
s++;
/*
* if the treename is added, we then have to skip the first
* part within the separators
*/
if (skip) {
skip = 0;
continue;
}
tmp = *s;
*s = 0;
rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
if (rc && rc == -EREMOTE) {
struct smb3_fs_context v = {NULL}; struct smb3_fs_context v = {NULL};
/* if @path contains a tree name, skip it in the prefix path */ /* if @path contains a tree name, skip it in the prefix path */
if (added_treename) { if (added_treename) {
rc = smb3_parse_devname(path, &v); rc = smb3_parse_devname(path, &v);
if (rc) if (rc)
break; goto out;
rc = -EREMOTE;
npath = build_unc_path_to_root(&v, cifs_sb, true); npath = build_unc_path_to_root(&v, cifs_sb, true);
smb3_cleanup_fs_context_contents(&v); smb3_cleanup_fs_context_contents(&v);
} else { } else {
...@@ -3346,16 +3317,18 @@ static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_contex ...@@ -3346,16 +3317,18 @@ static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_contex
v.prepath = path + 1; v.prepath = path + 1;
npath = build_unc_path_to_root(&v, cifs_sb, true); npath = build_unc_path_to_root(&v, cifs_sb, true);
} }
if (IS_ERR(npath)) { if (IS_ERR(npath)) {
rc = PTR_ERR(npath); rc = PTR_ERR(npath);
break; goto out;
} }
kfree(*dfs_path); kfree(*dfs_path);
*dfs_path = npath; *dfs_path = npath;
rc = -EREMOTE;
} }
*s = tmp;
} while (rc == 0);
out:
kfree(path); kfree(path);
return rc; return rc;
} }
...@@ -3441,8 +3414,8 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) ...@@ -3441,8 +3414,8 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
put_root_ses(root_ses); put_root_ses(root_ses);
set_root_ses(cifs_sb, ses, &root_ses); set_root_ses(cifs_sb, ses, &root_ses);
} }
/* Check for remaining path components and then continue chasing them (-EREMOTE) */ /* Get next dfs path and then continue chasing them if -EREMOTE */
rc = check_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path); rc = next_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path);
/* Prevent recursion on broken link referrals */ /* Prevent recursion on broken link referrals */
if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
rc = -ELOOP; rc = -ELOOP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment