aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-15 21:06:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-15 21:06:22 -0400
commit09c9b0eaa0773264b795c9e1bbb2c9816732573f (patch)
tree590059d3c7074a7579413a5d6a16f3cf140c325a
parentf0d98d85831bf1a3b1f56f8c14af60797aaca536 (diff)
parentc1596ff52466522c98013f1610797a85ba5d4e63 (diff)
Merge tag '4.17-rc1SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "SMB3 fixes, a few for stable, and some important cleanup work from Ronnie of the smb3 transport code" * tag '4.17-rc1SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: change validate_buf to validate_iov cifs: remove rfc1002 hardcoded constants from cifs_discard_remaining_data() cifs: Change SMB2_open to return an iov for the error parameter cifs: add resp_buf_size to the mid_q_entry structure smb3.11: replace a 4 with server->vals->header_preamble_size cifs: replace a 4 with server->vals->header_preamble_size cifs: add pdu_size to the TCP_Server_Info structure SMB311: Improve checking of negotiate security contexts SMB3: Fix length checking of SMB3.11 negotiate request CIFS: add ONCE flag for cifs_dbg type cifs: Use ULL suffix for 64-bit constant SMB3: Log at least once if tree connect fails during reconnect cifs: smb2pdu: Fix potential NULL pointer dereference
-rw-r--r--fs/cifs/cifs_debug.c17
-rw-r--r--fs/cifs/cifs_debug.h34
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/cifssmb.c11
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/inode.c2
-rw-r--r--fs/cifs/smb2misc.c42
-rw-r--r--fs/cifs/smb2ops.c18
-rw-r--r--fs/cifs/smb2pdu.c163
-rw-r--r--fs/cifs/smb2pdu.h10
-rw-r--r--fs/cifs/smb2proto.h2
-rw-r--r--fs/cifs/smb2transport.c2
-rw-r--r--fs/cifs/transport.c2
13 files changed, 240 insertions, 71 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index e35e711db68e..9d69ea433330 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -42,23 +42,6 @@ cifs_dump_mem(char *label, void *data, int length)
42 data, length, true); 42 data, length, true);
43} 43}
44 44
45#ifdef CONFIG_CIFS_DEBUG
46void cifs_vfs_err(const char *fmt, ...)
47{
48 struct va_format vaf;
49 va_list args;
50
51 va_start(args, fmt);
52
53 vaf.fmt = fmt;
54 vaf.va = &args;
55
56 pr_err_ratelimited("CIFS VFS: %pV", &vaf);
57
58 va_end(args);
59}
60#endif
61
62void cifs_dump_detail(void *buf) 45void cifs_dump_detail(void *buf)
63{ 46{
64#ifdef CONFIG_CIFS_DEBUG2 47#ifdef CONFIG_CIFS_DEBUG2
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index c611ca2339d7..fe5567655662 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -39,6 +39,7 @@ extern int cifsFYI;
39#else 39#else
40#define NOISY 0 40#define NOISY 0
41#endif 41#endif
42#define ONCE 8
42 43
43/* 44/*
44 * debug ON 45 * debug ON
@@ -46,19 +47,28 @@ extern int cifsFYI;
46 */ 47 */
47#ifdef CONFIG_CIFS_DEBUG 48#ifdef CONFIG_CIFS_DEBUG
48 49
49__printf(1, 2) void cifs_vfs_err(const char *fmt, ...);
50
51/* information message: e.g., configuration, major event */ 50/* information message: e.g., configuration, major event */
52#define cifs_dbg(type, fmt, ...) \ 51#define cifs_dbg_func(ratefunc, type, fmt, ...) \
53do { \ 52do { \
54 if (type == FYI && cifsFYI & CIFS_INFO) { \ 53 if ((type) & FYI && cifsFYI & CIFS_INFO) { \
55 pr_debug_ratelimited("%s: " \ 54 pr_debug_ ## ratefunc("%s: " \
56 fmt, __FILE__, ##__VA_ARGS__); \ 55 fmt, __FILE__, ##__VA_ARGS__); \
57 } else if (type == VFS) { \ 56 } else if ((type) & VFS) { \
58 cifs_vfs_err(fmt, ##__VA_ARGS__); \ 57 pr_err_ ## ratefunc("CuIFS VFS: " \
59 } else if (type == NOISY && type != 0) { \ 58 fmt, ##__VA_ARGS__); \
60 pr_debug_ratelimited(fmt, ##__VA_ARGS__); \ 59 } else if ((type) & NOISY && (NOISY != 0)) { \
61 } \ 60 pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \
61 } \
62} while (0)
63
64#define cifs_dbg(type, fmt, ...) \
65do { \
66 if ((type) & ONCE) \
67 cifs_dbg_func(once, \
68 type, fmt, ##__VA_ARGS__); \
69 else \
70 cifs_dbg_func(ratelimited, \
71 type, fmt, ##__VA_ARGS__); \
62} while (0) 72} while (0)
63 73
64/* 74/*
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 2282562e78a1..cb950a5fa078 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -665,6 +665,8 @@ struct TCP_Server_Info {
665 struct delayed_work echo; /* echo ping workqueue job */ 665 struct delayed_work echo; /* echo ping workqueue job */
666 char *smallbuf; /* pointer to current "small" buffer */ 666 char *smallbuf; /* pointer to current "small" buffer */
667 char *bigbuf; /* pointer to current "big" buffer */ 667 char *bigbuf; /* pointer to current "big" buffer */
668 /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
669 unsigned int pdu_size;
668 unsigned int total_read; /* total amount of data read in this pass */ 670 unsigned int total_read; /* total amount of data read in this pass */
669#ifdef CONFIG_CIFS_FSCACHE 671#ifdef CONFIG_CIFS_FSCACHE
670 struct fscache_cookie *fscache; /* client index cache cookie */ 672 struct fscache_cookie *fscache; /* client index cache cookie */
@@ -676,6 +678,7 @@ struct TCP_Server_Info {
676 unsigned int max_read; 678 unsigned int max_read;
677 unsigned int max_write; 679 unsigned int max_write;
678#ifdef CONFIG_CIFS_SMB311 680#ifdef CONFIG_CIFS_SMB311
681 __le16 cipher_type;
679 /* save initital negprot hash */ 682 /* save initital negprot hash */
680 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; 683 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
681#endif /* 3.1.1 */ 684#endif /* 3.1.1 */
@@ -1373,6 +1376,7 @@ struct mid_q_entry {
1373 mid_handle_t *handle; /* call handle mid callback */ 1376 mid_handle_t *handle; /* call handle mid callback */
1374 void *callback_data; /* general purpose pointer for callback */ 1377 void *callback_data; /* general purpose pointer for callback */
1375 void *resp_buf; /* pointer to received SMB header */ 1378 void *resp_buf; /* pointer to received SMB header */
1379 unsigned int resp_buf_size;
1376 int mid_state; /* wish this were enum but can not pass to wait_event */ 1380 int mid_state; /* wish this were enum but can not pass to wait_event */
1377 unsigned int mid_flags; 1381 unsigned int mid_flags;
1378 __le16 command; /* smb command code */ 1382 __le16 command; /* smb command code */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 59c09a596c0a..6d3e40d7029c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -206,8 +206,10 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
206 mutex_unlock(&ses->session_mutex); 206 mutex_unlock(&ses->session_mutex);
207 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 207 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
208 208
209 if (rc) 209 if (rc) {
210 printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
210 goto out; 211 goto out;
212 }
211 213
212 atomic_inc(&tconInfoReconnectCount); 214 atomic_inc(&tconInfoReconnectCount);
213 215
@@ -1416,8 +1418,9 @@ openRetry:
1416int 1418int
1417cifs_discard_remaining_data(struct TCP_Server_Info *server) 1419cifs_discard_remaining_data(struct TCP_Server_Info *server)
1418{ 1420{
1419 unsigned int rfclen = get_rfc1002_length(server->smallbuf); 1421 unsigned int rfclen = server->pdu_size;
1420 int remaining = rfclen + 4 - server->total_read; 1422 int remaining = rfclen + server->vals->header_preamble_size -
1423 server->total_read;
1421 1424
1422 while (remaining > 0) { 1425 while (remaining > 0) {
1423 int length; 1426 int length;
@@ -1454,7 +1457,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1454 unsigned int data_offset, data_len; 1457 unsigned int data_offset, data_len;
1455 struct cifs_readdata *rdata = mid->callback_data; 1458 struct cifs_readdata *rdata = mid->callback_data;
1456 char *buf = server->smallbuf; 1459 char *buf = server->smallbuf;
1457 unsigned int buflen = get_rfc1002_length(buf) + 1460 unsigned int buflen = server->pdu_size +
1458 server->vals->header_preamble_size; 1461 server->vals->header_preamble_size;
1459 bool use_rdma_mr = false; 1462 bool use_rdma_mr = false;
1460 1463
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4e0808f40195..e8830f076a7f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
772{ 772{
773 int length; 773 int length;
774 char *buf = server->smallbuf; 774 char *buf = server->smallbuf;
775 unsigned int pdu_length = get_rfc1002_length(buf); 775 unsigned int pdu_length = server->pdu_size;
776 776
777 /* make sure this will fit in a large buffer */ 777 /* make sure this will fit in a large buffer */
778 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 778 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
@@ -881,6 +881,7 @@ cifs_demultiplex_thread(void *p)
881 * so we can now interpret the length field. 881 * so we can now interpret the length field.
882 */ 882 */
883 pdu_length = get_rfc1002_length(buf); 883 pdu_length = get_rfc1002_length(buf);
884 server->pdu_size = pdu_length;
884 885
885 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); 886 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
886 if (!is_smb_response(server, buf[0])) 887 if (!is_smb_response(server, buf[0]))
@@ -927,6 +928,7 @@ cifs_demultiplex_thread(void *p)
927 928
928 server->lstrp = jiffies; 929 server->lstrp = jiffies;
929 if (mid_entry != NULL) { 930 if (mid_entry != NULL) {
931 mid_entry->resp_buf_size = server->pdu_size;
930 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && 932 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
931 mid_entry->mid_state == MID_RESPONSE_RECEIVED && 933 mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
932 server->ops->handle_cancelled_mid) 934 server->ops->handle_cancelled_mid)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f856df4adae3..3c371f7f5963 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -710,7 +710,7 @@ cgfi_exit:
710/* Simple function to return a 64 bit hash of string. Rarely called */ 710/* Simple function to return a 64 bit hash of string. Rarely called */
711static __u64 simple_hashstr(const char *str) 711static __u64 simple_hashstr(const char *str)
712{ 712{
713 const __u64 hash_mult = 1125899906842597L; /* a big enough prime */ 713 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
714 __u64 hash = 0; 714 __u64 hash = 0;
715 715
716 while (*str) 716 while (*str)
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 5406e95f5d92..68ea8491c160 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -93,6 +93,43 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
93 /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24) 93 /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
94}; 94};
95 95
96#ifdef CONFIG_CIFS_SMB311
97static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
98 size_t hdr_preamble_size)
99{
100 __u16 neg_count;
101 __u32 nc_offset, size_of_pad_before_neg_ctxts;
102 struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr;
103
104 /* Negotiate contexts are only valid for latest dialect SMB3.11 */
105 neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount);
106 if ((neg_count == 0) ||
107 (pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID)))
108 return 0;
109
110 /* Make sure that negotiate contexts start after gss security blob */
111 nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
112 if (nc_offset < non_ctxlen - hdr_preamble_size /* RFC1001 len */) {
113 printk_once(KERN_WARNING "invalid negotiate context offset\n");
114 return 0;
115 }
116 size_of_pad_before_neg_ctxts = nc_offset -
117 (non_ctxlen - hdr_preamble_size);
118
119 /* Verify that at least minimal negotiate contexts fit within frame */
120 if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
121 printk_once(KERN_WARNING "negotiate context goes beyond end\n");
122 return 0;
123 }
124
125 cifs_dbg(FYI, "length of negcontexts %d pad %d\n",
126 len - nc_offset, size_of_pad_before_neg_ctxts);
127
128 /* length of negcontexts including pad from end of sec blob to them */
129 return (len - nc_offset) + size_of_pad_before_neg_ctxts;
130}
131#endif /* CIFS_SMB311 */
132
96int 133int
97smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) 134smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
98{ 135{
@@ -198,6 +235,11 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
198 235
199 clc_len = smb2_calc_size(hdr); 236 clc_len = smb2_calc_size(hdr);
200 237
238#ifdef CONFIG_CIFS_SMB311
239 if (shdr->Command == SMB2_NEGOTIATE)
240 clc_len += get_neg_ctxt_len(hdr, len, clc_len,
241 srvr->vals->header_preamble_size);
242#endif /* SMB311 */
201 if (srvr->vals->header_preamble_size + len != clc_len) { 243 if (srvr->vals->header_preamble_size + len != clc_len) {
202 cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n", 244 cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
203 clc_len, srvr->vals->header_preamble_size + len, mid); 245 clc_len, srvr->vals->header_preamble_size + len, mid);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 968b1d43a1ea..b4ae932ea134 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1451,6 +1451,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1451 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 1451 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1452 struct cifs_open_parms oparms; 1452 struct cifs_open_parms oparms;
1453 struct cifs_fid fid; 1453 struct cifs_fid fid;
1454 struct kvec err_iov = {NULL, 0};
1454 struct smb2_err_rsp *err_buf = NULL; 1455 struct smb2_err_rsp *err_buf = NULL;
1455 struct smb2_symlink_err_rsp *symlink; 1456 struct smb2_symlink_err_rsp *symlink;
1456 unsigned int sub_len; 1457 unsigned int sub_len;
@@ -1473,15 +1474,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1473 oparms.fid = &fid; 1474 oparms.fid = &fid;
1474 oparms.reconnect = false; 1475 oparms.reconnect = false;
1475 1476
1476 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf); 1477 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
1477 1478
1478 if (!rc || !err_buf) { 1479 if (!rc || !err_buf) {
1479 kfree(utf16_path); 1480 kfree(utf16_path);
1480 return -ENOENT; 1481 return -ENOENT;
1481 } 1482 }
1482 1483
1484 err_buf = err_iov.iov_base;
1483 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || 1485 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
1484 get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) { 1486 err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
1485 kfree(utf16_path); 1487 kfree(utf16_path);
1486 return -ENOENT; 1488 return -ENOENT;
1487 } 1489 }
@@ -1494,13 +1496,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1494 print_len = le16_to_cpu(symlink->PrintNameLength); 1496 print_len = le16_to_cpu(symlink->PrintNameLength);
1495 print_offset = le16_to_cpu(symlink->PrintNameOffset); 1497 print_offset = le16_to_cpu(symlink->PrintNameOffset);
1496 1498
1497 if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size < 1499 if (err_iov.iov_len + server->vals->header_preamble_size <
1498 SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { 1500 SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
1499 kfree(utf16_path); 1501 kfree(utf16_path);
1500 return -ENOENT; 1502 return -ENOENT;
1501 } 1503 }
1502 1504
1503 if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size < 1505 if (err_iov.iov_len + server->vals->header_preamble_size <
1504 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { 1506 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
1505 kfree(utf16_path); 1507 kfree(utf16_path);
1506 return -ENOENT; 1508 return -ENOENT;
@@ -2550,7 +2552,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
2550 unsigned int npages; 2552 unsigned int npages;
2551 struct page **pages; 2553 struct page **pages;
2552 unsigned int len; 2554 unsigned int len;
2553 unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size; 2555 unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
2554 int rc; 2556 int rc;
2555 int i = 0; 2557 int i = 0;
2556 2558
@@ -2624,7 +2626,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
2624{ 2626{
2625 int length; 2627 int length;
2626 char *buf = server->smallbuf; 2628 char *buf = server->smallbuf;
2627 unsigned int pdu_length = get_rfc1002_length(buf); 2629 unsigned int pdu_length = server->pdu_size;
2628 unsigned int buf_size; 2630 unsigned int buf_size;
2629 struct mid_q_entry *mid_entry; 2631 struct mid_q_entry *mid_entry;
2630 2632
@@ -2668,7 +2670,7 @@ static int
2668smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) 2670smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
2669{ 2671{
2670 char *buf = server->smallbuf; 2672 char *buf = server->smallbuf;
2671 unsigned int pdu_length = get_rfc1002_length(buf); 2673 unsigned int pdu_length = server->pdu_size;
2672 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; 2674 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
2673 unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); 2675 unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
2674 2676
@@ -2699,7 +2701,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
2699{ 2701{
2700 char *buf = server->large_buf ? server->bigbuf : server->smallbuf; 2702 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
2701 2703
2702 return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 2704 return handle_read_data(server, mid, buf, server->pdu_size +
2703 server->vals->header_preamble_size, 2705 server->vals->header_preamble_size,
2704 NULL, 0, 0); 2706 NULL, 0, 0);
2705} 2707}
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index f7741cee2a4c..0f044c4a2dc9 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -268,8 +268,11 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
268 mutex_unlock(&tcon->ses->session_mutex); 268 mutex_unlock(&tcon->ses->session_mutex);
269 269
270 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 270 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
271 if (rc) 271 if (rc) {
272 /* If sess reconnected but tcon didn't, something strange ... */
273 printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
272 goto out; 274 goto out;
275 }
273 276
274 if (smb2_command != SMB2_INTERNAL_CMD) 277 if (smb2_command != SMB2_INTERNAL_CMD)
275 queue_delayed_work(cifsiod_wq, &server->reconnect, 0); 278 queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
@@ -403,6 +406,100 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
403 *total_len += 4 + sizeof(struct smb2_preauth_neg_context) 406 *total_len += 4 + sizeof(struct smb2_preauth_neg_context)
404 + sizeof(struct smb2_encryption_neg_context); 407 + sizeof(struct smb2_encryption_neg_context);
405} 408}
409
410static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
411{
412 unsigned int len = le16_to_cpu(ctxt->DataLength);
413
414 /* If invalid preauth context warn but use what we requested, SHA-512 */
415 if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
416 printk_once(KERN_WARNING "server sent bad preauth context\n");
417 return;
418 }
419 if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
420 printk_once(KERN_WARNING "illegal SMB3 hash algorithm count\n");
421 if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
422 printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n");
423}
424
425static int decode_encrypt_ctx(struct TCP_Server_Info *server,
426 struct smb2_encryption_neg_context *ctxt)
427{
428 unsigned int len = le16_to_cpu(ctxt->DataLength);
429
430 cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
431 if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
432 printk_once(KERN_WARNING "server sent bad crypto ctxt len\n");
433 return -EINVAL;
434 }
435
436 if (le16_to_cpu(ctxt->CipherCount) != 1) {
437 printk_once(KERN_WARNING "illegal SMB3.11 cipher count\n");
438 return -EINVAL;
439 }
440 cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0]));
441 if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
442 (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) {
443 printk_once(KERN_WARNING "invalid SMB3.11 cipher returned\n");
444 return -EINVAL;
445 }
446 server->cipher_type = ctxt->Ciphers[0];
447 return 0;
448}
449
450static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
451 struct TCP_Server_Info *server)
452{
453 struct smb2_neg_context *pctx;
454 unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
455 unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
456 unsigned int len_of_smb = be32_to_cpu(rsp->hdr.smb2_buf_length);
457 unsigned int len_of_ctxts, i;
458 int rc = 0;
459
460 cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
461 if (len_of_smb <= offset) {
462 cifs_dbg(VFS, "Invalid response: negotiate context offset\n");
463 return -EINVAL;
464 }
465
466 len_of_ctxts = len_of_smb - offset;
467
468 for (i = 0; i < ctxt_cnt; i++) {
469 int clen;
470 /* check that offset is not beyond end of SMB */
471 if (len_of_ctxts == 0)
472 break;
473
474 if (len_of_ctxts < sizeof(struct smb2_neg_context))
475 break;
476
477 pctx = (struct smb2_neg_context *)(offset +
478 server->vals->header_preamble_size + (char *)rsp);
479 clen = le16_to_cpu(pctx->DataLength);
480 if (clen > len_of_ctxts)
481 break;
482
483 if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
484 decode_preauth_context(
485 (struct smb2_preauth_neg_context *)pctx);
486 else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
487 rc = decode_encrypt_ctx(server,
488 (struct smb2_encryption_neg_context *)pctx);
489 else
490 cifs_dbg(VFS, "unknown negcontext of type %d ignored\n",
491 le16_to_cpu(pctx->ContextType));
492
493 if (rc)
494 break;
495 /* offsets must be 8 byte aligned */
496 clen = (clen + 7) & ~0x7;
497 offset += clen + sizeof(struct smb2_neg_context);
498 len_of_ctxts -= clen;
499 }
500 return rc;
501}
502
406#else 503#else
407static void assemble_neg_contexts(struct smb2_negotiate_req *req, 504static void assemble_neg_contexts(struct smb2_negotiate_req *req,
408 unsigned int *total_len) 505 unsigned int *total_len)
@@ -616,6 +713,15 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
616 else if (rc == 0) 713 else if (rc == 0)
617 rc = -EIO; 714 rc = -EIO;
618 } 715 }
716
717#ifdef CONFIG_CIFS_SMB311
718 if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
719 if (rsp->NegotiateContextCount)
720 rc = smb311_decode_neg_context(rsp, server);
721 else
722 cifs_dbg(VFS, "Missing expected negotiate contexts\n");
723 }
724#endif /* CONFIG_CIFS_SMB311 */
619neg_exit: 725neg_exit:
620 free_rsp_buf(resp_buftype, rsp); 726 free_rsp_buf(resp_buftype, rsp);
621 return rc; 727 return rc;
@@ -1026,7 +1132,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
1026 if (rc) 1132 if (rc)
1027 goto out; 1133 goto out;
1028 1134
1029 if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 != 1135 if (offsetof(struct smb2_sess_setup_rsp, Buffer) - ses->server->vals->header_preamble_size !=
1030 le16_to_cpu(rsp->SecurityBufferOffset)) { 1136 le16_to_cpu(rsp->SecurityBufferOffset)) {
1031 cifs_dbg(VFS, "Invalid security buffer offset %d\n", 1137 cifs_dbg(VFS, "Invalid security buffer offset %d\n",
1032 le16_to_cpu(rsp->SecurityBufferOffset)); 1138 le16_to_cpu(rsp->SecurityBufferOffset));
@@ -1701,7 +1807,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
1701int 1807int
1702SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, 1808SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1703 __u8 *oplock, struct smb2_file_all_info *buf, 1809 __u8 *oplock, struct smb2_file_all_info *buf,
1704 struct smb2_err_rsp **err_buf) 1810 struct kvec *err_iov)
1705{ 1811{
1706 struct smb2_create_req *req; 1812 struct smb2_create_req *req;
1707 struct smb2_create_rsp *rsp; 1813 struct smb2_create_rsp *rsp;
@@ -1841,9 +1947,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1841 1947
1842 if (rc != 0) { 1948 if (rc != 0) {
1843 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); 1949 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
1844 if (err_buf && rsp) 1950 if (err_iov && rsp) {
1845 *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4, 1951 *err_iov = rsp_iov;
1846 GFP_KERNEL); 1952 resp_buftype = CIFS_NO_BUFFER;
1953 rsp = NULL;
1954 }
1847 goto creat_exit; 1955 goto creat_exit;
1848 } 1956 }
1849 1957
@@ -2098,13 +2206,13 @@ close_exit:
2098} 2206}
2099 2207
2100static int 2208static int
2101validate_buf(unsigned int offset, unsigned int buffer_length, 2209validate_iov(struct TCP_Server_Info *server,
2102 struct smb2_hdr *hdr, unsigned int min_buf_size) 2210 unsigned int offset, unsigned int buffer_length,
2103 2211 struct kvec *iov, unsigned int min_buf_size)
2104{ 2212{
2105 unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length); 2213 unsigned int smb_len = iov->iov_len;
2106 char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr; 2214 char *end_of_smb = smb_len + server->vals->header_preamble_size + (char *)iov->iov_base;
2107 char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr; 2215 char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)iov->iov_base;
2108 char *end_of_buf = begin_of_buf + buffer_length; 2216 char *end_of_buf = begin_of_buf + buffer_length;
2109 2217
2110 2218
@@ -2134,18 +2242,18 @@ validate_buf(unsigned int offset, unsigned int buffer_length,
2134 * Caller must free buffer. 2242 * Caller must free buffer.
2135 */ 2243 */
2136static int 2244static int
2137validate_and_copy_buf(unsigned int offset, unsigned int buffer_length, 2245validate_and_copy_iov(struct TCP_Server_Info *server,
2138 struct smb2_hdr *hdr, unsigned int minbufsize, 2246 unsigned int offset, unsigned int buffer_length,
2247 struct kvec *iov, unsigned int minbufsize,
2139 char *data) 2248 char *data)
2140
2141{ 2249{
2142 char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr; 2250 char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)(iov->iov_base);
2143 int rc; 2251 int rc;
2144 2252
2145 if (!data) 2253 if (!data)
2146 return -EINVAL; 2254 return -EINVAL;
2147 2255
2148 rc = validate_buf(offset, buffer_length, hdr, minbufsize); 2256 rc = validate_iov(server, offset, buffer_length, iov, minbufsize);
2149 if (rc) 2257 if (rc)
2150 return rc; 2258 return rc;
2151 2259
@@ -2223,9 +2331,10 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
2223 } 2331 }
2224 } 2332 }
2225 2333
2226 rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset), 2334 rc = validate_and_copy_iov(ses->server,
2335 le16_to_cpu(rsp->OutputBufferOffset),
2227 le32_to_cpu(rsp->OutputBufferLength), 2336 le32_to_cpu(rsp->OutputBufferLength),
2228 &rsp->hdr, min_len, *data); 2337 &rsp_iov, min_len, *data);
2229 2338
2230qinf_exit: 2339qinf_exit:
2231 free_rsp_buf(resp_buftype, rsp); 2340 free_rsp_buf(resp_buftype, rsp);
@@ -3146,8 +3255,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
3146 goto qdir_exit; 3255 goto qdir_exit;
3147 } 3256 }
3148 3257
3149 rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset), 3258 rc = validate_iov(server,
3150 le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr, 3259 le16_to_cpu(rsp->OutputBufferOffset),
3260 le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
3151 info_buf_size); 3261 info_buf_size);
3152 if (rc) 3262 if (rc)
3153 goto qdir_exit; 3263 goto qdir_exit;
@@ -3454,7 +3564,7 @@ static int
3454build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, 3564build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
3455 int outbuf_len, u64 persistent_fid, u64 volatile_fid) 3565 int outbuf_len, u64 persistent_fid, u64 volatile_fid)
3456{ 3566{
3457 struct TCP_Server_Info *server = tcon->ses->server; 3567 struct TCP_Server_Info *server;
3458 int rc; 3568 int rc;
3459 struct smb2_query_info_req *req; 3569 struct smb2_query_info_req *req;
3460 unsigned int total_len; 3570 unsigned int total_len;
@@ -3464,6 +3574,8 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
3464 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) 3574 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
3465 return -EIO; 3575 return -EIO;
3466 3576
3577 server = tcon->ses->server;
3578
3467 rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, 3579 rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req,
3468 &total_len); 3580 &total_len);
3469 if (rc) 3581 if (rc)
@@ -3517,8 +3629,9 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
3517 3629
3518 info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size + 3630 info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
3519 le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr); 3631 le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
3520 rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset), 3632 rc = validate_iov(server,
3521 le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr, 3633 le16_to_cpu(rsp->OutputBufferOffset),
3634 le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
3522 sizeof(struct smb2_fs_full_size_info)); 3635 sizeof(struct smb2_fs_full_size_info));
3523 if (!rc) 3636 if (!rc)
3524 copy_fs_info_to_kstatfs(info, fsdata); 3637 copy_fs_info_to_kstatfs(info, fsdata);
@@ -3574,7 +3687,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
3574 3687
3575 rsp_len = le32_to_cpu(rsp->OutputBufferLength); 3688 rsp_len = le32_to_cpu(rsp->OutputBufferLength);
3576 offset = le16_to_cpu(rsp->OutputBufferOffset); 3689 offset = le16_to_cpu(rsp->OutputBufferOffset);
3577 rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len); 3690 rc = validate_iov(server, offset, rsp_len, &rsp_iov, min_len);
3578 if (rc) 3691 if (rc)
3579 goto qfsattr_exit; 3692 goto qfsattr_exit;
3580 3693
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 253e2c7c952f..6093e5142b2b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -263,11 +263,19 @@ struct smb2_negotiate_req {
263#define SMB2_NT_FIND 0x00100000 263#define SMB2_NT_FIND 0x00100000
264#define SMB2_LARGE_FILES 0x00200000 264#define SMB2_LARGE_FILES 0x00200000
265 265
266struct smb2_neg_context {
267 __le16 ContextType;
268 __le16 DataLength;
269 __le32 Reserved;
270 /* Followed by array of data */
271} __packed;
272
266#define SMB311_SALT_SIZE 32 273#define SMB311_SALT_SIZE 32
267/* Hash Algorithm Types */ 274/* Hash Algorithm Types */
268#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001) 275#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
269#define SMB2_PREAUTH_HASH_SIZE 64 276#define SMB2_PREAUTH_HASH_SIZE 64
270 277
278#define MIN_PREAUTH_CTXT_DATA_LEN (SMB311_SALT_SIZE + 6)
271struct smb2_preauth_neg_context { 279struct smb2_preauth_neg_context {
272 __le16 ContextType; /* 1 */ 280 __le16 ContextType; /* 1 */
273 __le16 DataLength; 281 __le16 DataLength;
@@ -282,6 +290,8 @@ struct smb2_preauth_neg_context {
282#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001) 290#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001)
283#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002) 291#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002)
284 292
293/* Min encrypt context data is one cipher so 2 bytes + 2 byte count field */
294#define MIN_ENCRYPT_CTXT_DATA_LEN 4
285struct smb2_encryption_neg_context { 295struct smb2_encryption_neg_context {
286 __le16 ContextType; /* 2 */ 296 __le16 ContextType; /* 2 */
287 __le16 DataLength; 297 __le16 DataLength;
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index cbcce3f7e86f..8ba24a95db71 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -122,7 +122,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
122extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, 122extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
123 __le16 *path, __u8 *oplock, 123 __le16 *path, __u8 *oplock,
124 struct smb2_file_all_info *buf, 124 struct smb2_file_all_info *buf,
125 struct smb2_err_rsp **err_buf); 125 struct kvec *err_iov);
126extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, 126extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
127 u64 persistent_fid, u64 volatile_fid, u32 opcode, 127 u64 persistent_fid, u64 volatile_fid, u32 opcode,
128 bool is_fsctl, char *in_data, u32 indatalen, 128 bool is_fsctl, char *in_data, u32 indatalen,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index bf49cb73b9e6..8806f3f76c1d 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -604,7 +604,7 @@ int
604smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, 604smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
605 bool log_error) 605 bool log_error)
606{ 606{
607 unsigned int len = get_rfc1002_length(mid->resp_buf); 607 unsigned int len = mid->resp_buf_size;
608 struct kvec iov[2]; 608 struct kvec iov[2];
609 struct smb_rqst rqst = { .rq_iov = iov, 609 struct smb_rqst rqst = { .rq_iov = iov,
610 .rq_nvec = 2 }; 610 .rq_nvec = 2 };
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 279718dcb2ed..8f6f25918229 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -790,7 +790,7 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
790 790
791 buf = (char *)midQ->resp_buf; 791 buf = (char *)midQ->resp_buf;
792 resp_iov->iov_base = buf; 792 resp_iov->iov_base = buf;
793 resp_iov->iov_len = get_rfc1002_length(buf) + 793 resp_iov->iov_len = midQ->resp_buf_size +
794 ses->server->vals->header_preamble_size; 794 ses->server->vals->header_preamble_size;
795 if (midQ->large_buf) 795 if (midQ->large_buf)
796 *resp_buf_type = CIFS_LARGE_BUFFER; 796 *resp_buf_type = CIFS_LARGE_BUFFER;