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

Pull smb client fixes from Steve French:
"Six smb3 client fixes, including three for stable, from the SMB
plugfest (testing event) this week:

- Reparse point handling fix (found when investigating dir
enumeration when fifo in dir)

- Fix excessive thread creation for dir lease cleanup

- UAF fix in negotiate path

- remove duplicate error message mapping and fix confusing warning
message

- add dynamic trace point to improve debugging RDMA connection
attempts"

* tag '6.6-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb3: fix confusing debug message
smb: client: handle STATUS_IO_REPARSE_TAG_NOT_HANDLED
smb3: remove duplicate error mapping
cifs: Fix UAF in cifs_demultiplex_thread()
smb3: do not start laundromat thread when dir leases disabled
smb3: Add dynamic trace points for RDMA (smbdirect) reconnect

+60 -27
+6
fs/smb/client/cached_dir.c
··· 452 struct cached_fid *cfid, *q; 453 LIST_HEAD(entry); 454 455 spin_lock(&cfids->cfid_list_lock); 456 list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { 457 list_move(&cfid->entry, &entry); ··· 653 { 654 struct cached_fid *cfid, *q; 655 LIST_HEAD(entry); 656 657 if (cfids->laundromat) { 658 kthread_stop(cfids->laundromat);
··· 452 struct cached_fid *cfid, *q; 453 LIST_HEAD(entry); 454 455 + if (cfids == NULL) 456 + return; 457 + 458 spin_lock(&cfids->cfid_list_lock); 459 list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { 460 list_move(&cfid->entry, &entry); ··· 650 { 651 struct cached_fid *cfid, *q; 652 LIST_HEAD(entry); 653 + 654 + if (cfids == NULL) 655 + return; 656 657 if (cfids->laundromat) { 658 kthread_stop(cfids->laundromat);
+2 -1
fs/smb/client/cifsglob.h
··· 1807 #define MID_RETRY_NEEDED 8 /* session closed while this request out */ 1808 #define MID_RESPONSE_MALFORMED 0x10 1809 #define MID_SHUTDOWN 0x20 1810 1811 /* Flags */ 1812 #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ ··· 1944 * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once 1945 * ->can_cache_brlcks 1946 * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc 1947 - * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc 1948 * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo 1949 * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo 1950 * ->invalidHandle initiate_cifs_search
··· 1807 #define MID_RETRY_NEEDED 8 /* session closed while this request out */ 1808 #define MID_RESPONSE_MALFORMED 0x10 1809 #define MID_SHUTDOWN 0x20 1810 + #define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */ 1811 1812 /* Flags */ 1813 #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ ··· 1943 * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once 1944 * ->can_cache_brlcks 1945 * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc 1946 + * cached_fid->fid_mutex cifs_tcon->crfid tcon_info_alloc 1947 * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo 1948 * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo 1949 * ->invalidHandle initiate_cifs_search
+1 -1
fs/smb/client/cifsproto.h
··· 512 513 extern struct cifs_ses *sesInfoAlloc(void); 514 extern void sesInfoFree(struct cifs_ses *); 515 - extern struct cifs_tcon *tconInfoAlloc(void); 516 extern void tconInfoFree(struct cifs_tcon *); 517 518 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
··· 512 513 extern struct cifs_ses *sesInfoAlloc(void); 514 extern void sesInfoFree(struct cifs_ses *); 515 + extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled); 516 extern void tconInfoFree(struct cifs_tcon *); 517 518 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+6 -2
fs/smb/client/connect.c
··· 1882 } 1883 } 1884 1885 - tcon = tconInfoAlloc(); 1886 if (tcon == NULL) 1887 return -ENOMEM; 1888 ··· 2493 goto out_fail; 2494 } 2495 2496 - tcon = tconInfoAlloc(); 2497 if (tcon == NULL) { 2498 rc = -ENOMEM; 2499 goto out_fail;
··· 1882 } 1883 } 1884 1885 + /* no need to setup directory caching on IPC share, so pass in false */ 1886 + tcon = tcon_info_alloc(false); 1887 if (tcon == NULL) 1888 return -ENOMEM; 1889 ··· 2492 goto out_fail; 2493 } 2494 2495 + if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) 2496 + tcon = tcon_info_alloc(true); 2497 + else 2498 + tcon = tcon_info_alloc(false); 2499 if (tcon == NULL) { 2500 rc = -ENOMEM; 2501 goto out_fail;
+9 -5
fs/smb/client/misc.c
··· 113 } 114 115 struct cifs_tcon * 116 - tconInfoAlloc(void) 117 { 118 struct cifs_tcon *ret_buf; 119 120 ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); 121 if (!ret_buf) 122 return NULL; 123 - ret_buf->cfids = init_cached_dirs(); 124 - if (!ret_buf->cfids) { 125 - kfree(ret_buf); 126 - return NULL; 127 } 128 129 atomic_inc(&tconInfoAllocCount); 130 ret_buf->status = TID_NEW;
··· 113 } 114 115 struct cifs_tcon * 116 + tcon_info_alloc(bool dir_leases_enabled) 117 { 118 struct cifs_tcon *ret_buf; 119 120 ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); 121 if (!ret_buf) 122 return NULL; 123 + 124 + if (dir_leases_enabled == true) { 125 + ret_buf->cfids = init_cached_dirs(); 126 + if (!ret_buf->cfids) { 127 + kfree(ret_buf); 128 + return NULL; 129 + } 130 } 131 + /* else ret_buf->cfids is already set to NULL above */ 132 133 atomic_inc(&tconInfoAllocCount); 134 ret_buf->status = TID_NEW;
+3
fs/smb/client/smb2inode.c
··· 539 int rc = 0; 540 541 switch (rsp->hdr.Status) { 542 case STATUS_STOPPED_ON_SYMLINK: 543 rc = smb2_parse_symlink_response(cifs_sb, iov, 544 &data->symlink_target);
··· 539 int rc = 0; 540 541 switch (rsp->hdr.Status) { 542 + case STATUS_IO_REPARSE_TAG_NOT_HANDLED: 543 + reparse_point = true; 544 + break; 545 case STATUS_STOPPED_ON_SYMLINK: 546 rc = smb2_parse_symlink_response(cifs_sb, iov, 547 &data->symlink_target);
-2
fs/smb/client/smb2maperror.c
··· 877 "STATUS_IO_REPARSE_TAG_MISMATCH"}, 878 {STATUS_IO_REPARSE_DATA_INVALID, -EIO, 879 "STATUS_IO_REPARSE_DATA_INVALID"}, 880 - {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EIO, 881 - "STATUS_IO_REPARSE_TAG_NOT_HANDLED"}, 882 {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO, 883 "STATUS_REPARSE_POINT_NOT_RESOLVED"}, 884 {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO,
··· 877 "STATUS_IO_REPARSE_TAG_MISMATCH"}, 878 {STATUS_IO_REPARSE_DATA_INVALID, -EIO, 879 "STATUS_IO_REPARSE_DATA_INVALID"}, 880 {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO, 881 "STATUS_REPARSE_POINT_NOT_RESOLVED"}, 882 {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO,
+2 -2
fs/smb/client/smb2pdu.c
··· 848 849 iov[num].iov_base = create_posix_buf(mode); 850 if (mode == ACL_NO_MODE) 851 - cifs_dbg(FYI, "Invalid mode\n"); 852 if (iov[num].iov_base == NULL) 853 return -ENOMEM; 854 iov[num].iov_len = sizeof(struct create_posix); ··· 3878 goto done; 3879 3880 /* allocate a dummy tcon struct used for reconnect */ 3881 - tcon = tconInfoAlloc(); 3882 if (!tcon) { 3883 resched = true; 3884 list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
··· 848 849 iov[num].iov_base = create_posix_buf(mode); 850 if (mode == ACL_NO_MODE) 851 + cifs_dbg(FYI, "%s: no mode\n", __func__); 852 if (iov[num].iov_base == NULL) 853 return -ENOMEM; 854 iov[num].iov_len = sizeof(struct create_posix); ··· 3878 goto done; 3879 3880 /* allocate a dummy tcon struct used for reconnect */ 3881 + tcon = tcon_info_alloc(false); 3882 if (!tcon) { 3883 resched = true; 3884 list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
+6 -3
fs/smb/client/smbdirect.c
··· 1401 server->smbd_conn = smbd_get_connection( 1402 server, (struct sockaddr *) &server->dstaddr); 1403 1404 - if (server->smbd_conn) 1405 cifs_dbg(VFS, "RDMA transport re-established\n"); 1406 - 1407 - return server->smbd_conn ? 0 : -ENOENT; 1408 } 1409 1410 static void destroy_caches_and_workqueue(struct smbd_connection *info)
··· 1401 server->smbd_conn = smbd_get_connection( 1402 server, (struct sockaddr *) &server->dstaddr); 1403 1404 + if (server->smbd_conn) { 1405 cifs_dbg(VFS, "RDMA transport re-established\n"); 1406 + trace_smb3_smbd_connect_done(server->hostname, server->conn_id, &server->dstaddr); 1407 + return 0; 1408 + } 1409 + trace_smb3_smbd_connect_err(server->hostname, server->conn_id, &server->dstaddr); 1410 + return -ENOENT; 1411 } 1412 1413 static void destroy_caches_and_workqueue(struct smbd_connection *info)
+2
fs/smb/client/trace.h
··· 935 TP_ARGS(hostname, conn_id, addr)) 936 937 DEFINE_SMB3_CONNECT_EVENT(connect_done); 938 939 DECLARE_EVENT_CLASS(smb3_connect_err_class, 940 TP_PROTO(char *hostname, __u64 conn_id,
··· 935 TP_ARGS(hostname, conn_id, addr)) 936 937 DEFINE_SMB3_CONNECT_EVENT(connect_done); 938 + DEFINE_SMB3_CONNECT_EVENT(smbd_connect_done); 939 + DEFINE_SMB3_CONNECT_EVENT(smbd_connect_err); 940 941 DECLARE_EVENT_CLASS(smb3_connect_err_class, 942 TP_PROTO(char *hostname, __u64 conn_id,
+23 -11
fs/smb/client/transport.c
··· 35 void 36 cifs_wake_up_task(struct mid_q_entry *mid) 37 { 38 wake_up_process(mid->callback_data); 39 } 40 ··· 89 struct TCP_Server_Info *server = midEntry->server; 90 91 if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && 92 - midEntry->mid_state == MID_RESPONSE_RECEIVED && 93 server->ops->handle_cancelled_mid) 94 server->ops->handle_cancelled_mid(midEntry, server); 95 ··· 740 int error; 741 742 error = wait_event_state(server->response_q, 743 - midQ->mid_state != MID_REQUEST_SUBMITTED, 744 (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); 745 if (error < 0) 746 return -ERESTARTSYS; ··· 894 895 spin_lock(&server->mid_lock); 896 switch (mid->mid_state) { 897 - case MID_RESPONSE_RECEIVED: 898 spin_unlock(&server->mid_lock); 899 return rc; 900 case MID_RETRY_NEEDED: ··· 993 credits.instance = server->reconnect_instance; 994 995 add_credits(server, &credits, mid->optype); 996 } 997 998 static void ··· 1216 send_cancel(server, &rqst[i], midQ[i]); 1217 spin_lock(&server->mid_lock); 1218 midQ[i]->mid_flags |= MID_WAIT_CANCELLED; 1219 - if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { 1220 midQ[i]->callback = cifs_cancelled_callback; 1221 cancelled_mid[i] = true; 1222 credits[i].value = 0; ··· 1238 } 1239 1240 if (!midQ[i]->resp_buf || 1241 - midQ[i]->mid_state != MID_RESPONSE_RECEIVED) { 1242 rc = -EIO; 1243 cifs_dbg(FYI, "Bad MID state?\n"); 1244 goto out; ··· 1425 if (rc != 0) { 1426 send_cancel(server, &rqst, midQ); 1427 spin_lock(&server->mid_lock); 1428 - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 1429 /* no longer considered to be "in-flight" */ 1430 midQ->callback = release_mid; 1431 spin_unlock(&server->mid_lock); ··· 1443 } 1444 1445 if (!midQ->resp_buf || !out_buf || 1446 - midQ->mid_state != MID_RESPONSE_RECEIVED) { 1447 rc = -EIO; 1448 cifs_server_dbg(VFS, "Bad MID state?\n"); 1449 goto out; ··· 1567 1568 /* Wait for a reply - allow signals to interrupt. */ 1569 rc = wait_event_interruptible(server->response_q, 1570 - (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || 1571 ((server->tcpStatus != CifsGood) && 1572 (server->tcpStatus != CifsNew))); 1573 1574 /* Were we interrupted by a signal ? */ 1575 spin_lock(&server->srv_lock); 1576 if ((rc == -ERESTARTSYS) && 1577 - (midQ->mid_state == MID_REQUEST_SUBMITTED) && 1578 ((server->tcpStatus == CifsGood) || 1579 (server->tcpStatus == CifsNew))) { 1580 spin_unlock(&server->srv_lock); ··· 1607 if (rc) { 1608 send_cancel(server, &rqst, midQ); 1609 spin_lock(&server->mid_lock); 1610 - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 1611 /* no longer considered to be "in-flight" */ 1612 midQ->callback = release_mid; 1613 spin_unlock(&server->mid_lock); ··· 1628 return rc; 1629 1630 /* rcvd frame is ok */ 1631 - if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { 1632 rc = -EIO; 1633 cifs_tcon_dbg(VFS, "Bad MID state?\n"); 1634 goto out;
··· 35 void 36 cifs_wake_up_task(struct mid_q_entry *mid) 37 { 38 + if (mid->mid_state == MID_RESPONSE_RECEIVED) 39 + mid->mid_state = MID_RESPONSE_READY; 40 wake_up_process(mid->callback_data); 41 } 42 ··· 87 struct TCP_Server_Info *server = midEntry->server; 88 89 if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && 90 + (midEntry->mid_state == MID_RESPONSE_RECEIVED || 91 + midEntry->mid_state == MID_RESPONSE_READY) && 92 server->ops->handle_cancelled_mid) 93 server->ops->handle_cancelled_mid(midEntry, server); 94 ··· 737 int error; 738 739 error = wait_event_state(server->response_q, 740 + midQ->mid_state != MID_REQUEST_SUBMITTED && 741 + midQ->mid_state != MID_RESPONSE_RECEIVED, 742 (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); 743 if (error < 0) 744 return -ERESTARTSYS; ··· 890 891 spin_lock(&server->mid_lock); 892 switch (mid->mid_state) { 893 + case MID_RESPONSE_READY: 894 spin_unlock(&server->mid_lock); 895 return rc; 896 case MID_RETRY_NEEDED: ··· 989 credits.instance = server->reconnect_instance; 990 991 add_credits(server, &credits, mid->optype); 992 + 993 + if (mid->mid_state == MID_RESPONSE_RECEIVED) 994 + mid->mid_state = MID_RESPONSE_READY; 995 } 996 997 static void ··· 1209 send_cancel(server, &rqst[i], midQ[i]); 1210 spin_lock(&server->mid_lock); 1211 midQ[i]->mid_flags |= MID_WAIT_CANCELLED; 1212 + if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED || 1213 + midQ[i]->mid_state == MID_RESPONSE_RECEIVED) { 1214 midQ[i]->callback = cifs_cancelled_callback; 1215 cancelled_mid[i] = true; 1216 credits[i].value = 0; ··· 1230 } 1231 1232 if (!midQ[i]->resp_buf || 1233 + midQ[i]->mid_state != MID_RESPONSE_READY) { 1234 rc = -EIO; 1235 cifs_dbg(FYI, "Bad MID state?\n"); 1236 goto out; ··· 1417 if (rc != 0) { 1418 send_cancel(server, &rqst, midQ); 1419 spin_lock(&server->mid_lock); 1420 + if (midQ->mid_state == MID_REQUEST_SUBMITTED || 1421 + midQ->mid_state == MID_RESPONSE_RECEIVED) { 1422 /* no longer considered to be "in-flight" */ 1423 midQ->callback = release_mid; 1424 spin_unlock(&server->mid_lock); ··· 1434 } 1435 1436 if (!midQ->resp_buf || !out_buf || 1437 + midQ->mid_state != MID_RESPONSE_READY) { 1438 rc = -EIO; 1439 cifs_server_dbg(VFS, "Bad MID state?\n"); 1440 goto out; ··· 1558 1559 /* Wait for a reply - allow signals to interrupt. */ 1560 rc = wait_event_interruptible(server->response_q, 1561 + (!(midQ->mid_state == MID_REQUEST_SUBMITTED || 1562 + midQ->mid_state == MID_RESPONSE_RECEIVED)) || 1563 ((server->tcpStatus != CifsGood) && 1564 (server->tcpStatus != CifsNew))); 1565 1566 /* Were we interrupted by a signal ? */ 1567 spin_lock(&server->srv_lock); 1568 if ((rc == -ERESTARTSYS) && 1569 + (midQ->mid_state == MID_REQUEST_SUBMITTED || 1570 + midQ->mid_state == MID_RESPONSE_RECEIVED) && 1571 ((server->tcpStatus == CifsGood) || 1572 (server->tcpStatus == CifsNew))) { 1573 spin_unlock(&server->srv_lock); ··· 1596 if (rc) { 1597 send_cancel(server, &rqst, midQ); 1598 spin_lock(&server->mid_lock); 1599 + if (midQ->mid_state == MID_REQUEST_SUBMITTED || 1600 + midQ->mid_state == MID_RESPONSE_RECEIVED) { 1601 /* no longer considered to be "in-flight" */ 1602 midQ->callback = release_mid; 1603 spin_unlock(&server->mid_lock); ··· 1616 return rc; 1617 1618 /* rcvd frame is ok */ 1619 + if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) { 1620 rc = -EIO; 1621 cifs_tcon_dbg(VFS, "Bad MID state?\n"); 1622 goto out;