History

Merge tag '6.2-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French: "cifs/smb3 client fixes: - two multichannel fixes - three reconnect fixes - unmap fix" * tag '6.2-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix interface count calculation during refresh cifs: refcount only the selected iface during interface update cifs: protect access of TCP_Server_Info::{dstaddr,hostname} cifs: fix race in assemble_neg_contexts() cifs: ignore ipc reconnect failures during dfs failover cifs: Fix kmap_local_page() unmapping

Linus Torvalds committed 3 years ago

Commit f18fca92 parents 0007c04 cc7d79d5 files · +27 −26Browse files

Unified · Split

5 files
  1. fs/cifs/dfs.c +12 −13
  2. fs/cifs/misc.c +2 −0
  3. fs/cifs/sess.c +2 −1
  4. fs/cifs/smb2ops.c +4 −8
  5. fs/cifs/smb2pdu.c +7 −4
fs/cifs/dfs.c+12−13
@@ -327,8 +327,8 @@ static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb · 326 unmodified lines
327327 return rc;
328328 }
329329
330−static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host,
331− size_t tcp_host_len, char *share, bool *target_match)
330+static int target_share_matches_server(struct TCP_Server_Info *server, char *share,
331+ bool *target_match)
332332 {
333333 int rc = 0;
334334 const char *dfs_host;
@@ -338,13 +338,16 @@ static int target_share_matches_server(struct TCP_Server_Info *server, const cha · 3 unmodified lines
338338 extract_unc_hostname(share, &dfs_host, &dfs_host_len);
339339
340340 /* Check if hostnames or addresses match */
341− if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
342− cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
343− dfs_host, (int)tcp_host_len, tcp_host);
341+ cifs_server_lock(server);
342+ if (dfs_host_len != strlen(server->hostname) ||
343+ strncasecmp(dfs_host, server->hostname, dfs_host_len)) {
344+ cifs_dbg(FYI, "%s: %.*s doesn't match %s\n", __func__,
345+ (int)dfs_host_len, dfs_host, server->hostname);
344346 rc = match_target_ip(server, dfs_host, dfs_host_len, target_match);
345347 if (rc)
346348 cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
347349 }
350+ cifs_server_unlock(server);
348351 return rc;
349352 }
350353
@@ -358,13 +361,9 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 7 unmodified lines
358361 struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses);
359362 struct cifs_tcon *ipc = root_ses->tcon_ipc;
360363 char *share = NULL, *prefix = NULL;
361− const char *tcp_host;
362− size_t tcp_host_len;
363364 struct dfs_cache_tgt_iterator *tit;
364365 bool target_match;
365366
366− extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
367−
368367 tit = dfs_cache_get_tgt_iterator(tl);
369368 if (!tit) {
370369 rc = -ENOENT;
@@ -387,8 +386,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 16 unmodified lines
387386 break;
388387 }
389388
390− rc = target_share_matches_server(server, tcp_host, tcp_host_len, share,
391− &target_match);
389+ rc = target_share_matches_server(server, share, &target_match);
392390 if (rc)
393391 break;
394392 if (!target_match) {
@@ -401,8 +399,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 6 unmodified lines
401399 if (ipc->need_reconnect) {
402400 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
403401 rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls);
404− if (rc)
405− break;
402+ cifs_dbg(FYI, "%s: reconnect ipc: %d\n", __func__, rc);
406403 }
407404
408405 scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
@@ -498,7 +495,9 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru · 89 unmodified lines
498495 }
499496
500497 if (tcon->ipc) {
498+ cifs_server_lock(server);
501499 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
500+ cifs_server_unlock(server);
502501 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
503502 goto out;
504503 }
fs/cifs/misc.c+2−0
@@ -1277,7 +1277,9 @@ int match_target_ip(struct TCP_Server_Info *server, · 1276 unmodified lines
12771277 if (rc < 0)
12781278 return rc;
12791279
1280+ spin_lock(&server->srv_lock);
12801281 *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
1282+ spin_unlock(&server->srv_lock);
12811283 cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
12821284 return 0;
12831285 }
fs/cifs/sess.c+2−1
@@ -292,9 +292,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) · 291 unmodified lines
292292 continue;
293293 }
294294 kref_get(&iface->refcount);
295+ break;
295296 }
296297
297− if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) {
298+ if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
298299 rc = 1;
299300 iface = NULL;
300301 cifs_dbg(FYI, "unable to find a suitable iface\n");
fs/cifs/smb2ops.c+4−8
@@ -530,7 +530,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 529 unmodified lines
530530 p = buf;
531531
532532 spin_lock(&ses->iface_lock);
533− ses->iface_count = 0;
534533 /*
535534 * Go through iface_list and do kref_put to remove
536535 * any unused ifaces. ifaces in use will be removed
@@ -540,6 +539,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 3 unmodified lines
540539 iface_head) {
541540 iface->is_active = 0;
542541 kref_put(&iface->refcount, release_iface);
542+ ses->iface_count--;
543543 }
544544 spin_unlock(&ses->iface_lock);
545545
@@ -618,6 +618,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 72 unmodified lines
618618 /* just get a ref so that it doesn't get picked/freed */
619619 iface->is_active = 1;
620620 kref_get(&iface->refcount);
621+ ses->iface_count++;
621622 spin_unlock(&ses->iface_lock);
622623 goto next_iface;
623624 } else if (ret < 0) {
@@ -4488,17 +4489,12 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, · 3864 unmodified lines
44884489
44894490 /* copy pages form the old */
44904491 for (j = 0; j < npages; j++) {
4491− char *dst, *src;
44924492 unsigned int offset, len;
44934493
44944494 rqst_page_get_length(new, j, &len, &offset);
44954495
4496− dst = kmap_local_page(new->rq_pages[j]) + offset;
4497− src = kmap_local_page(old->rq_pages[j]) + offset;
4498−
4499− memcpy(dst, src, len);
4500− kunmap(new->rq_pages[j]);
4501− kunmap(old->rq_pages[j]);
4496+ memcpy_page(new->rq_pages[j], offset,
4497+ old->rq_pages[j], offset, len);
45024498 }
45034499 }
45044500
fs/cifs/smb2pdu.c+7−4
@@ -541,9 +541,10 @@ static void · 540 unmodified lines
541541 assemble_neg_contexts(struct smb2_negotiate_req *req,
542542 struct TCP_Server_Info *server, unsigned int *total_len)
543543 {
544− char *pneg_ctxt;
545− char *hostname = NULL;
546544 unsigned int ctxt_len, neg_context_count;
545+ struct TCP_Server_Info *pserver;
546+ char *pneg_ctxt;
547+ char *hostname;
547548
548549 if (*total_len > 200) {
549550 /* In case length corrupted don't want to overrun smb buffer */
@@ -574,8 +575,9 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, · 24 unmodified lines
574575 * secondary channels don't have the hostname field populated
575576 * use the hostname field in the primary channel instead
576577 */
577− hostname = CIFS_SERVER_IS_CHAN(server) ?
578− server->primary_server->hostname : server->hostname;
578+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
579+ cifs_server_lock(pserver);
580+ hostname = pserver->hostname;
579581 if (hostname && (hostname[0] != 0)) {
580582 ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
581583 hostname);
@@ -584,6 +586,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, · 2 unmodified lines
584586 neg_context_count = 3;
585587 } else
586588 neg_context_count = 2;
589+ cifs_server_unlock(pserver);
587590
588591 build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
589592 *total_len += sizeof(struct smb2_posix_neg_context);