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