diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-14 19:51:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-14 19:51:29 -0400 |
commit | 5466f4dfce857a7954f19bc9acfc7ca4a73321b6 (patch) | |
tree | 6b3b8f3e7afd3dc0b0249574b30ae3920ef3ee40 | |
parent | 82f1faa86727de976e38eade5e96a1846742d71e (diff) | |
parent | 67dbea2ce6873f8ba57988ba3e608e8bf61c347f (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.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 15 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 6 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 4 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 19 |
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); | |||
79 | extern void cifs_wake_up_task(struct mid_q_entry *mid); | 79 | extern void cifs_wake_up_task(struct mid_q_entry *mid); |
80 | extern int cifs_handle_standard(struct TCP_Server_Info *server, | 80 | extern int cifs_handle_standard(struct TCP_Server_Info *server, |
81 | struct mid_q_entry *mid); | 81 | struct mid_q_entry *mid); |
82 | extern int cifs_discard_remaining_data(struct TCP_Server_Info *server, | 82 | extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); |
83 | char *buf); | ||
84 | extern int cifs_call_async(struct TCP_Server_Info *server, | 83 | extern 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 | */ |
1402 | int | 1402 | int |
1403 | cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf) | 1403 | cifs_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); |
3027 | error: | 3027 | error: |
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; |
2223 | discard_data: | 2223 | discard_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: | |||
1277 | tcon_error_exit: | 1276 | tcon_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 */ |