Skip to content

Commit 7f28af9

Browse files
Paulo Alcantarasmfrench
authored andcommitted
cifs: fix potential use-after-free bugs
Ensure that share and prefix variables are set to NULL after kfree() when looping through DFS targets in __tree_connect_dfs_target(). Also, get rid of @ref in __tree_connect_dfs_target() and just pass a boolean to indicate whether we're handling link targets or not. Fixes: c88f7dc ("cifs: support nested dfs links over reconnect") Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 869da64 commit 7f28af9

File tree

1 file changed

+19
-22
lines changed

1 file changed

+19
-22
lines changed

fs/cifs/connect.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4141,14 +4141,13 @@ static int target_share_matches_server(struct TCP_Server_Info *server, const cha
41414141
}
41424142

41434143
static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
4144-
struct cifs_sb_info *cifs_sb, char *tree,
4145-
struct dfs_cache_tgt_list *tl, struct dfs_info3_param *ref)
4144+
struct cifs_sb_info *cifs_sb, char *tree, bool islink,
4145+
struct dfs_cache_tgt_list *tl)
41464146
{
41474147
int rc;
41484148
struct TCP_Server_Info *server = tcon->ses->server;
41494149
const struct smb_version_operations *ops = server->ops;
41504150
struct cifs_tcon *ipc = tcon->ses->tcon_ipc;
4151-
bool islink;
41524151
char *share = NULL, *prefix = NULL;
41534152
const char *tcp_host;
41544153
size_t tcp_host_len;
@@ -4157,9 +4156,6 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
41574156

41584157
extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
41594158

4160-
islink = ref->server_type == DFS_TYPE_LINK;
4161-
free_dfs_info_param(ref);
4162-
41634159
tit = dfs_cache_get_tgt_iterator(tl);
41644160
if (!tit) {
41654161
rc = -ENOENT;
@@ -4173,6 +4169,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
41734169

41744170
kfree(share);
41754171
kfree(prefix);
4172+
share = prefix = NULL;
41764173

41774174
/* Check if share matches with tcp ses */
41784175
rc = dfs_cache_get_tgt_share(server->current_fullpath + 1, tit, &share, &prefix);
@@ -4209,25 +4206,23 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
42094206
* newly resolved target.
42104207
*/
42114208
if (dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, cifs_remap(cifs_sb), target,
4212-
ref, &ntl)) {
4209+
NULL, &ntl)) {
42134210
rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
42144211
if (rc)
42154212
continue;
42164213
rc = dfs_cache_noreq_update_tgthint(server->current_fullpath + 1, tit);
42174214
if (!rc)
42184215
rc = cifs_update_super_prepath(cifs_sb, prefix);
4219-
break;
4220-
}
4221-
/* Target is another dfs share */
4222-
rc = update_server_fullpath(server, cifs_sb, target);
4223-
dfs_cache_free_tgts(tl);
4224-
4225-
if (!rc) {
4226-
rc = -EREMOTE;
4227-
list_replace_init(&ntl.tl_list, &tl->tl_list);
42284216
} else {
4229-
dfs_cache_free_tgts(&ntl);
4230-
free_dfs_info_param(ref);
4217+
/* Target is another dfs share */
4218+
rc = update_server_fullpath(server, cifs_sb, target);
4219+
dfs_cache_free_tgts(tl);
4220+
4221+
if (!rc) {
4222+
rc = -EREMOTE;
4223+
list_replace_init(&ntl.tl_list, &tl->tl_list);
4224+
} else
4225+
dfs_cache_free_tgts(&ntl);
42314226
}
42324227
break;
42334228
}
@@ -4240,15 +4235,15 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
42404235
}
42414236

42424237
static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
4243-
struct cifs_sb_info *cifs_sb, char *tree,
4244-
struct dfs_cache_tgt_list *tl, struct dfs_info3_param *ref)
4238+
struct cifs_sb_info *cifs_sb, char *tree, bool islink,
4239+
struct dfs_cache_tgt_list *tl)
42454240
{
42464241
int rc;
42474242
int num_links = 0;
42484243
struct TCP_Server_Info *server = tcon->ses->server;
42494244

42504245
do {
4251-
rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, tl, ref);
4246+
rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, islink, tl);
42524247
if (!rc || rc != -EREMOTE)
42534248
break;
42544249
} while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
@@ -4302,7 +4297,9 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
43024297
goto out;
43034298
}
43044299

4305-
rc = tree_connect_dfs_target(xid, tcon, cifs_sb, tree, &tl, &ref);
4300+
rc = tree_connect_dfs_target(xid, tcon, cifs_sb, tree, ref.server_type == DFS_TYPE_LINK,
4301+
&tl);
4302+
free_dfs_info_param(&ref);
43064303

43074304
out:
43084305
kfree(tree);

0 commit comments

Comments
 (0)