aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-04-14 19:51:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-04-14 19:51:29 -0400
commit5466f4dfce857a7954f19bc9acfc7ca4a73321b6 (patch)
tree6b3b8f3e7afd3dc0b0249574b30ae3920ef3ee40
parent82f1faa86727de976e38eade5e96a1846742d71e (diff)
parent67dbea2ce6873f8ba57988ba3e608e8bf61c347f (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull more CIFS fixes from Steve French: "As promised, here is the remaining set of cifs/smb3 fixes for stable (and a fix for one regression) now that they have had additional review and testing" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: Fix SMB3 mount without specifying a security mechanism CIFS: store results of cifs_reopen_file to avoid infinite wait CIFS: remove bad_network_name flag CIFS: reconnect thread reschedule itself CIFS: handle guest access errors to Windows shares CIFS: Fix null pointer deref during read resp processing
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c15
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/smb2ops.c4
-rw-r--r--fs/cifs/smb2pdu.c19
7 files changed, 29 insertions, 22 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index d07f13a63369..37f5a41cc50c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -948,7 +948,6 @@ struct cifs_tcon {
948 bool use_persistent:1; /* use persistent instead of durable handles */ 948 bool use_persistent:1; /* use persistent instead of durable handles */
949#ifdef CONFIG_CIFS_SMB2 949#ifdef CONFIG_CIFS_SMB2
950 bool print:1; /* set if connection to printer share */ 950 bool print:1; /* set if connection to printer share */
951 bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
952 __le32 capabilities; 951 __le32 capabilities;
953 __u32 share_flags; 952 __u32 share_flags;
954 __u32 maximal_access; 953 __u32 maximal_access;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ec5e5e514fdd..97e5d236d265 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -79,8 +79,7 @@ extern void cifs_delete_mid(struct mid_q_entry *mid);
79extern void cifs_wake_up_task(struct mid_q_entry *mid); 79extern void cifs_wake_up_task(struct mid_q_entry *mid);
80extern int cifs_handle_standard(struct TCP_Server_Info *server, 80extern int cifs_handle_standard(struct TCP_Server_Info *server,
81 struct mid_q_entry *mid); 81 struct mid_q_entry *mid);
82extern int cifs_discard_remaining_data(struct TCP_Server_Info *server, 82extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
83 char *buf);
84extern int cifs_call_async(struct TCP_Server_Info *server, 83extern int cifs_call_async(struct TCP_Server_Info *server,
85 struct smb_rqst *rqst, 84 struct smb_rqst *rqst,
86 mid_receive_t *receive, mid_callback_t *callback, 85 mid_receive_t *receive, mid_callback_t *callback,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 967b92631807..5d21f00ae341 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1400,9 +1400,9 @@ openRetry:
1400 * current bigbuf. 1400 * current bigbuf.
1401 */ 1401 */
1402int 1402int
1403cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf) 1403cifs_discard_remaining_data(struct TCP_Server_Info *server)
1404{ 1404{
1405 unsigned int rfclen = get_rfc1002_length(buf); 1405 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1406 int remaining = rfclen + 4 - server->total_read; 1406 int remaining = rfclen + 4 - server->total_read;
1407 1407
1408 while (remaining > 0) { 1408 while (remaining > 0) {
@@ -1426,8 +1426,10 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1426 int length; 1426 int length;
1427 struct cifs_readdata *rdata = mid->callback_data; 1427 struct cifs_readdata *rdata = mid->callback_data;
1428 1428
1429 length = cifs_discard_remaining_data(server, mid->resp_buf); 1429 length = cifs_discard_remaining_data(server);
1430 dequeue_mid(mid, rdata->result); 1430 dequeue_mid(mid, rdata->result);
1431 mid->resp_buf = server->smallbuf;
1432 server->smallbuf = NULL;
1431 return length; 1433 return length;
1432} 1434}
1433 1435
@@ -1459,7 +1461,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1459 1461
1460 if (server->ops->is_status_pending && 1462 if (server->ops->is_status_pending &&
1461 server->ops->is_status_pending(buf, server, 0)) { 1463 server->ops->is_status_pending(buf, server, 0)) {
1462 cifs_discard_remaining_data(server, buf); 1464 cifs_discard_remaining_data(server);
1463 return -1; 1465 return -1;
1464 } 1466 }
1465 1467
@@ -1519,9 +1521,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", 1521 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1520 rdata->iov[0].iov_base, server->total_read); 1522 rdata->iov[0].iov_base, server->total_read);
1521 1523
1522 mid->resp_buf = server->smallbuf;
1523 server->smallbuf = NULL;
1524
1525 /* how much data is in the response? */ 1524 /* how much data is in the response? */
1526 data_len = server->ops->read_data_length(buf); 1525 data_len = server->ops->read_data_length(buf);
1527 if (data_offset + data_len > buflen) { 1526 if (data_offset + data_len > buflen) {
@@ -1544,6 +1543,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1544 return cifs_readv_discard(server, mid); 1543 return cifs_readv_discard(server, mid);
1545 1544
1546 dequeue_mid(mid, false); 1545 dequeue_mid(mid, false);
1546 mid->resp_buf = server->smallbuf;
1547 server->smallbuf = NULL;
1547 return length; 1548 return length;
1548} 1549}
1549 1550
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0c7596cef4b8..d82467cfb0e2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3753,6 +3753,9 @@ try_mount_again:
3753 if (IS_ERR(tcon)) { 3753 if (IS_ERR(tcon)) {
3754 rc = PTR_ERR(tcon); 3754 rc = PTR_ERR(tcon);
3755 tcon = NULL; 3755 tcon = NULL;
3756 if (rc == -EACCES)
3757 goto mount_fail_check;
3758
3756 goto remote_path_check; 3759 goto remote_path_check;
3757 } 3760 }
3758 3761
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index aa3debbba826..21d404535739 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2597,7 +2597,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
2597 wdata->credits = credits; 2597 wdata->credits = credits;
2598 2598
2599 if (!wdata->cfile->invalidHandle || 2599 if (!wdata->cfile->invalidHandle ||
2600 !cifs_reopen_file(wdata->cfile, false)) 2600 !(rc = cifs_reopen_file(wdata->cfile, false)))
2601 rc = server->ops->async_writev(wdata, 2601 rc = server->ops->async_writev(wdata,
2602 cifs_uncached_writedata_release); 2602 cifs_uncached_writedata_release);
2603 if (rc) { 2603 if (rc) {
@@ -3022,7 +3022,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
3022 rdata->credits = credits; 3022 rdata->credits = credits;
3023 3023
3024 if (!rdata->cfile->invalidHandle || 3024 if (!rdata->cfile->invalidHandle ||
3025 !cifs_reopen_file(rdata->cfile, true)) 3025 !(rc = cifs_reopen_file(rdata->cfile, true)))
3026 rc = server->ops->async_readv(rdata); 3026 rc = server->ops->async_readv(rdata);
3027error: 3027error:
3028 if (rc) { 3028 if (rc) {
@@ -3617,7 +3617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
3617 } 3617 }
3618 3618
3619 if (!rdata->cfile->invalidHandle || 3619 if (!rdata->cfile->invalidHandle ||
3620 !cifs_reopen_file(rdata->cfile, true)) 3620 !(rc = cifs_reopen_file(rdata->cfile, true)))
3621 rc = server->ops->async_readv(rdata); 3621 rc = server->ops->async_readv(rdata);
3622 if (rc) { 3622 if (rc) {
3623 add_credits_and_wake_if(server, rdata->credits, 0); 3623 add_credits_and_wake_if(server, rdata->credits, 0);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 7b12a727947e..152e37f2ad92 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2195,7 +2195,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
2195 if (rc) 2195 if (rc)
2196 goto free_pages; 2196 goto free_pages;
2197 2197
2198 rc = cifs_discard_remaining_data(server, buf); 2198 rc = cifs_discard_remaining_data(server);
2199 if (rc) 2199 if (rc)
2200 goto free_pages; 2200 goto free_pages;
2201 2201
@@ -2221,7 +2221,7 @@ free_pages:
2221 kfree(pages); 2221 kfree(pages);
2222 return rc; 2222 return rc;
2223discard_data: 2223discard_data:
2224 cifs_discard_remaining_data(server, buf); 2224 cifs_discard_remaining_data(server);
2225 goto free_pages; 2225 goto free_pages;
2226} 2226}
2227 2227
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 66fa1b941cdf..02da648041fc 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -562,8 +562,10 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
562 * but for time being this is our only auth choice so doesn't matter. 562 * but for time being this is our only auth choice so doesn't matter.
563 * We just found a server which sets blob length to zero expecting raw. 563 * We just found a server which sets blob length to zero expecting raw.
564 */ 564 */
565 if (blob_length == 0) 565 if (blob_length == 0) {
566 cifs_dbg(FYI, "missing security blob on negprot\n"); 566 cifs_dbg(FYI, "missing security blob on negprot\n");
567 server->sec_ntlmssp = true;
568 }
567 569
568 rc = cifs_enable_signing(server, ses->sign); 570 rc = cifs_enable_signing(server, ses->sign);
569 if (rc) 571 if (rc)
@@ -1171,9 +1173,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
1171 else 1173 else
1172 return -EIO; 1174 return -EIO;
1173 1175
1174 if (tcon && tcon->bad_network_name)
1175 return -ENOENT;
1176
1177 unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); 1176 unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
1178 if (unc_path == NULL) 1177 if (unc_path == NULL)
1179 return -ENOMEM; 1178 return -ENOMEM;
@@ -1277,8 +1276,6 @@ tcon_exit:
1277tcon_error_exit: 1276tcon_error_exit:
1278 if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { 1277 if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
1279 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); 1278 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
1280 if (tcon)
1281 tcon->bad_network_name = true;
1282 } 1279 }
1283 goto tcon_exit; 1280 goto tcon_exit;
1284} 1281}
@@ -2181,6 +2178,9 @@ void smb2_reconnect_server(struct work_struct *work)
2181 struct cifs_tcon *tcon, *tcon2; 2178 struct cifs_tcon *tcon, *tcon2;
2182 struct list_head tmp_list; 2179 struct list_head tmp_list;
2183 int tcon_exist = false; 2180 int tcon_exist = false;
2181 int rc;
2182 int resched = false;
2183
2184 2184
2185 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ 2185 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
2186 mutex_lock(&server->reconnect_mutex); 2186 mutex_lock(&server->reconnect_mutex);
@@ -2208,13 +2208,18 @@ void smb2_reconnect_server(struct work_struct *work)
2208 spin_unlock(&cifs_tcp_ses_lock); 2208 spin_unlock(&cifs_tcp_ses_lock);
2209 2209
2210 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { 2210 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
2211 if (!smb2_reconnect(SMB2_INTERNAL_CMD, tcon)) 2211 rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon);
2212 if (!rc)
2212 cifs_reopen_persistent_handles(tcon); 2213 cifs_reopen_persistent_handles(tcon);
2214 else
2215 resched = true;
2213 list_del_init(&tcon->rlist); 2216 list_del_init(&tcon->rlist);
2214 cifs_put_tcon(tcon); 2217 cifs_put_tcon(tcon);
2215 } 2218 }
2216 2219
2217 cifs_dbg(FYI, "Reconnecting tcons finished\n"); 2220 cifs_dbg(FYI, "Reconnecting tcons finished\n");
2221 if (resched)
2222 queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
2218 mutex_unlock(&server->reconnect_mutex); 2223 mutex_unlock(&server->reconnect_mutex);
2219 2224
2220 /* now we can safely release srv struct */ 2225 /* now we can safely release srv struct */