Message ID | 20221229214346.9979-1-pc@cjr.nz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | cifs: protect access of TCP_Server_Info::{dstaddr,hostname} | expand |
merged into cifs-2.6.git for-next pending testing On Thu, Dec 29, 2022 at 3:43 PM Paulo Alcantara <pc@cjr.nz> wrote: > > Use the appropriate locks to protect access of hostname and dstaddr > fields in cifs_tree_connect() as they might get changed by other > tasks. > > Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > --- > fs/cifs/dfs.c | 22 +++++++++++----------- > fs/cifs/misc.c | 2 ++ > 2 files changed, 13 insertions(+), 11 deletions(-) > > diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c > index 30086f2060a1..b64d20374b9c 100644 > --- a/fs/cifs/dfs.c > +++ b/fs/cifs/dfs.c > @@ -327,8 +327,8 @@ static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb > return rc; > } > > -static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host, > - size_t tcp_host_len, char *share, bool *target_match) > +static int target_share_matches_server(struct TCP_Server_Info *server, char *share, > + bool *target_match) > { > int rc = 0; > const char *dfs_host; > @@ -338,13 +338,16 @@ static int target_share_matches_server(struct TCP_Server_Info *server, const cha > extract_unc_hostname(share, &dfs_host, &dfs_host_len); > > /* Check if hostnames or addresses match */ > - if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { > - cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, > - dfs_host, (int)tcp_host_len, tcp_host); > + cifs_server_lock(server); > + if (dfs_host_len != strlen(server->hostname) || > + strncasecmp(dfs_host, server->hostname, dfs_host_len)) { > + cifs_dbg(FYI, "%s: %.*s doesn't match %s\n", __func__, > + (int)dfs_host_len, dfs_host, server->hostname); > rc = match_target_ip(server, dfs_host, dfs_host_len, target_match); > if (rc) > cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); > } > + cifs_server_unlock(server); > return rc; > } > > @@ -358,13 +361,9 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t > struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses); > struct cifs_tcon *ipc = root_ses->tcon_ipc; > char *share = NULL, *prefix = NULL; > - const char *tcp_host; > - size_t tcp_host_len; > struct dfs_cache_tgt_iterator *tit; > bool target_match; > > - extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); > - > tit = dfs_cache_get_tgt_iterator(tl); > if (!tit) { > rc = -ENOENT; > @@ -387,8 +386,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t > break; > } > > - rc = target_share_matches_server(server, tcp_host, tcp_host_len, share, > - &target_match); > + rc = target_share_matches_server(server, share, &target_match); > if (rc) > break; > if (!target_match) { > @@ -497,7 +495,9 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru > } > > if (tcon->ipc) { > + cifs_server_lock(server); > scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); > + cifs_server_unlock(server); > rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); > goto out; > } > diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c > index 4d3c586785a5..2a19c7987c5b 100644 > --- a/fs/cifs/misc.c > +++ b/fs/cifs/misc.c > @@ -1277,7 +1277,9 @@ int match_target_ip(struct TCP_Server_Info *server, > if (rc < 0) > return rc; > > + spin_lock(&server->srv_lock); > *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss); > + spin_unlock(&server->srv_lock); > cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); > return 0; > } > -- > 2.39.0 >
diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c index 30086f2060a1..b64d20374b9c 100644 --- a/fs/cifs/dfs.c +++ b/fs/cifs/dfs.c @@ -327,8 +327,8 @@ static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb return rc; } -static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host, - size_t tcp_host_len, char *share, bool *target_match) +static int target_share_matches_server(struct TCP_Server_Info *server, char *share, + bool *target_match) { int rc = 0; const char *dfs_host; @@ -338,13 +338,16 @@ static int target_share_matches_server(struct TCP_Server_Info *server, const cha extract_unc_hostname(share, &dfs_host, &dfs_host_len); /* Check if hostnames or addresses match */ - if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { - cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, - dfs_host, (int)tcp_host_len, tcp_host); + cifs_server_lock(server); + if (dfs_host_len != strlen(server->hostname) || + strncasecmp(dfs_host, server->hostname, dfs_host_len)) { + cifs_dbg(FYI, "%s: %.*s doesn't match %s\n", __func__, + (int)dfs_host_len, dfs_host, server->hostname); rc = match_target_ip(server, dfs_host, dfs_host_len, target_match); if (rc) cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); } + cifs_server_unlock(server); return rc; } @@ -358,13 +361,9 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses); struct cifs_tcon *ipc = root_ses->tcon_ipc; char *share = NULL, *prefix = NULL; - const char *tcp_host; - size_t tcp_host_len; struct dfs_cache_tgt_iterator *tit; bool target_match; - extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); - tit = dfs_cache_get_tgt_iterator(tl); if (!tit) { rc = -ENOENT; @@ -387,8 +386,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t break; } - rc = target_share_matches_server(server, tcp_host, tcp_host_len, share, - &target_match); + rc = target_share_matches_server(server, share, &target_match); if (rc) break; if (!target_match) { @@ -497,7 +495,9 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru } if (tcon->ipc) { + cifs_server_lock(server); scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); + cifs_server_unlock(server); rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); goto out; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 4d3c586785a5..2a19c7987c5b 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1277,7 +1277,9 @@ int match_target_ip(struct TCP_Server_Info *server, if (rc < 0) return rc; + spin_lock(&server->srv_lock); *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss); + spin_unlock(&server->srv_lock); cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); return 0; }
Use the appropriate locks to protect access of hostname and dstaddr fields in cifs_tree_connect() as they might get changed by other tasks. Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> --- fs/cifs/dfs.c | 22 +++++++++++----------- fs/cifs/misc.c | 2 ++ 2 files changed, 13 insertions(+), 11 deletions(-)