diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-15 21:06:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-15 21:06:22 -0400 |
commit | 09c9b0eaa0773264b795c9e1bbb2c9816732573f (patch) | |
tree | 590059d3c7074a7579413a5d6a16f3cf140c325a | |
parent | f0d98d85831bf1a3b1f56f8c14af60797aaca536 (diff) | |
parent | c1596ff52466522c98013f1610797a85ba5d4e63 (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.c | 17 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 34 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 11 | ||||
-rw-r--r-- | fs/cifs/connect.c | 4 | ||||
-rw-r--r-- | fs/cifs/inode.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 42 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 18 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 163 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 10 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 2 | ||||
-rw-r--r-- | fs/cifs/transport.c | 2 |
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 | ||
46 | void 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 | |||
62 | void cifs_dump_detail(void *buf) | 45 | void 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, ...) \ |
53 | do { \ | 52 | do { \ |
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, ...) \ | ||
65 | do { \ | ||
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: | |||
1416 | int | 1418 | int |
1417 | cifs_discard_remaining_data(struct TCP_Server_Info *server) | 1419 | cifs_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 */ |
711 | static __u64 simple_hashstr(const char *str) | 711 | static __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 | ||
97 | static __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 | |||
96 | int | 133 | int |
97 | smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | 134 | smb2_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 | |||
2668 | smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) | 2670 | smb3_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 | |||
410 | static 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 | |||
425 | static 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 | |||
450 | static 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 |
407 | static void assemble_neg_contexts(struct smb2_negotiate_req *req, | 504 | static 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 */ | ||
619 | neg_exit: | 725 | neg_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, | |||
1701 | int | 1807 | int |
1702 | SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | 1808 | SMB2_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 | ||
2100 | static int | 2208 | static int |
2101 | validate_buf(unsigned int offset, unsigned int buffer_length, | 2209 | validate_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 | */ |
2136 | static int | 2244 | static int |
2137 | validate_and_copy_buf(unsigned int offset, unsigned int buffer_length, | 2245 | validate_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 | ||
2230 | qinf_exit: | 2339 | qinf_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 | |||
3454 | build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, | 3564 | build_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 | ||
266 | struct 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) | ||
271 | struct smb2_preauth_neg_context { | 279 | struct 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 | ||
285 | struct smb2_encryption_neg_context { | 295 | struct 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); | |||
122 | extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, | 122 | extern 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); |
126 | extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, | 126 | extern 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 | |||
604 | smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | 604 | smb2_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; |