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
327 return rc;327 return rc;
328}328}
329 329
330static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host,330static int target_share_matches_server(struct TCP_Server_Info *server, char *share,
331 size_t tcp_host_len, char *share, bool *target_match)331 bool *target_match)
332{332{
333 int rc = 0;333 int rc = 0;
334 const char *dfs_host;334 const char *dfs_host;
@@ -338,13 +338,16 @@ static int target_share_matches_server(struct TCP_Server_Info *server, const cha · 3 unmodified lines
338 extract_unc_hostname(share, &dfs_host, &dfs_host_len);338 extract_unc_hostname(share, &dfs_host, &dfs_host_len);
339 339
340 /* Check if hostnames or addresses match */340 /* Check if hostnames or addresses match */
341 if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {341 cifs_server_lock(server);
342 cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,342 if (dfs_host_len != strlen(server->hostname) ||
343 dfs_host, (int)tcp_host_len, tcp_host);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);
344 rc = match_target_ip(server, dfs_host, dfs_host_len, target_match);346 rc = match_target_ip(server, dfs_host, dfs_host_len, target_match);
345 if (rc)347 if (rc)
346 cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);348 cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
347 }349 }
350 cifs_server_unlock(server);
348 return rc;351 return rc;
349}352}
350 353
@@ -358,13 +361,9 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 7 unmodified lines
358 struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses);361 struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses);
359 struct cifs_tcon *ipc = root_ses->tcon_ipc;362 struct cifs_tcon *ipc = root_ses->tcon_ipc;
360 char *share = NULL, *prefix = NULL;363 char *share = NULL, *prefix = NULL;
361 const char *tcp_host;
362 size_t tcp_host_len;
363 struct dfs_cache_tgt_iterator *tit;364 struct dfs_cache_tgt_iterator *tit;
364 bool target_match;365 bool target_match;
365 366
366 extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
367
368 tit = dfs_cache_get_tgt_iterator(tl);367 tit = dfs_cache_get_tgt_iterator(tl);
369 if (!tit) {368 if (!tit) {
370 rc = -ENOENT;369 rc = -ENOENT;
@@ -387,8 +386,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 16 unmodified lines
387 break;386 break;
388 }387 }
389 388
390 rc = target_share_matches_server(server, tcp_host, tcp_host_len, share,389 rc = target_share_matches_server(server, share, &target_match);
391 &target_match);
392 if (rc)390 if (rc)
393 break;391 break;
394 if (!target_match) {392 if (!target_match) {
@@ -401,8 +399,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 6 unmodified lines
401 if (ipc->need_reconnect) {399 if (ipc->need_reconnect) {
402 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);400 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
403 rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls);401 rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls);
404 if (rc)402 cifs_dbg(FYI, "%s: reconnect ipc: %d\n", __func__, rc);
405 break;
406 }403 }
407 404
408 scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);405 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
498 }495 }
499 496
500 if (tcon->ipc) {497 if (tcon->ipc) {
498 cifs_server_lock(server);
501 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);499 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
500 cifs_server_unlock(server);
502 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);501 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
503 goto out;502 goto out;
504 }503 }
fs/cifs/misc.c+2−0
@@ -1277,7 +1277,9 @@ int match_target_ip(struct TCP_Server_Info *server, · 1276 unmodified lines
1277 if (rc < 0)1277 if (rc < 0)
1278 return rc;1278 return rc;
1279 1279
1280 spin_lock(&server->srv_lock);
1280 *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);1281 *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
1282 spin_unlock(&server->srv_lock);
1281 cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);1283 cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
1282 return 0;1284 return 0;
1283}1285}
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
292 continue;292 continue;
293 }293 }
294 kref_get(&iface->refcount);294 kref_get(&iface->refcount);
295 break;
295 }296 }
296 297
297 if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) {298 if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
298 rc = 1;299 rc = 1;
299 iface = NULL;300 iface = NULL;
300 cifs_dbg(FYI, "unable to find a suitable iface\n");301 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
530 p = buf;530 p = buf;
531 531
532 spin_lock(&ses->iface_lock);532 spin_lock(&ses->iface_lock);
533 ses->iface_count = 0;
534 /*533 /*
535 * Go through iface_list and do kref_put to remove534 * Go through iface_list and do kref_put to remove
536 * any unused ifaces. ifaces in use will be removed535 * 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
540 iface_head) {539 iface_head) {
541 iface->is_active = 0;540 iface->is_active = 0;
542 kref_put(&iface->refcount, release_iface);541 kref_put(&iface->refcount, release_iface);
542 ses->iface_count--;
543 }543 }
544 spin_unlock(&ses->iface_lock);544 spin_unlock(&ses->iface_lock);
545 545
@@ -618,6 +618,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 72 unmodified lines
618 /* just get a ref so that it doesn't get picked/freed */618 /* just get a ref so that it doesn't get picked/freed */
619 iface->is_active = 1;619 iface->is_active = 1;
620 kref_get(&iface->refcount);620 kref_get(&iface->refcount);
621 ses->iface_count++;
621 spin_unlock(&ses->iface_lock);622 spin_unlock(&ses->iface_lock);
622 goto next_iface;623 goto next_iface;
623 } else if (ret < 0) {624 } else if (ret < 0) {
@@ -4488,17 +4489,12 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, · 3864 unmodified lines
4488 4489
4489 /* copy pages form the old */4490 /* copy pages form the old */
4490 for (j = 0; j < npages; j++) {4491 for (j = 0; j < npages; j++) {
4491 char *dst, *src;
4492 unsigned int offset, len;4492 unsigned int offset, len;
4493 4493
4494 rqst_page_get_length(new, j, &len, &offset);4494 rqst_page_get_length(new, j, &len, &offset);
4495 4495
4496 dst = kmap_local_page(new->rq_pages[j]) + offset;4496 memcpy_page(new->rq_pages[j], offset,
4497 src = kmap_local_page(old->rq_pages[j]) + offset;4497 old->rq_pages[j], offset, len);
4498
4499 memcpy(dst, src, len);
4500 kunmap(new->rq_pages[j]);
4501 kunmap(old->rq_pages[j]);
4502 }4498 }
4503 }4499 }
4504 4500
fs/cifs/smb2pdu.c+7−4
@@ -541,9 +541,10 @@ static void · 540 unmodified lines
541assemble_neg_contexts(struct smb2_negotiate_req *req,541assemble_neg_contexts(struct smb2_negotiate_req *req,
542 struct TCP_Server_Info *server, unsigned int *total_len)542 struct TCP_Server_Info *server, unsigned int *total_len)
543{543{
544 char *pneg_ctxt;
545 char *hostname = NULL;
546 unsigned int ctxt_len, neg_context_count;544 unsigned int ctxt_len, neg_context_count;
545 struct TCP_Server_Info *pserver;
546 char *pneg_ctxt;
547 char *hostname;
547 548
548 if (*total_len > 200) {549 if (*total_len > 200) {
549 /* In case length corrupted don't want to overrun smb buffer */550 /* 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
574 * secondary channels don't have the hostname field populated575 * secondary channels don't have the hostname field populated
575 * use the hostname field in the primary channel instead576 * use the hostname field in the primary channel instead
576 */577 */
577 hostname = CIFS_SERVER_IS_CHAN(server) ?578 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
578 server->primary_server->hostname : server->hostname;579 cifs_server_lock(pserver);
580 hostname = pserver->hostname;
579 if (hostname && (hostname[0] != 0)) {581 if (hostname && (hostname[0] != 0)) {
580 ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,582 ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
581 hostname);583 hostname);
@@ -584,6 +586,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, · 2 unmodified lines
584 neg_context_count = 3;586 neg_context_count = 3;
585 } else587 } else
586 neg_context_count = 2;588 neg_context_count = 2;
589 cifs_server_unlock(pserver);
587 590
588 build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);591 build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
589 *total_len += sizeof(struct smb2_posix_neg_context);592 *total_len += sizeof(struct smb2_posix_neg_context);