diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 21:38:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 21:38:47 -0500 |
commit | 2bfe01eff4307409b95859e860261d0907149b61 (patch) | |
tree | 51fd41be8e8df6057c3dde1eafdaa476b9200bea | |
parent | cab7076a185e1e27f6879325e4da762424c3f1c9 (diff) | |
parent | ae6f8dd4d0c87bfb72da9d9b56342adf53e69c31 (diff) |
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS/SMB3 updates from Steve French:
"Includes support for a critical SMB3 security feature: per-share
encryption from Pavel, and a cleanup from Jean Delvare.
Will have another cifs/smb3 merge next week"
* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
CIFS: Allow to switch on encryption with seal mount option
CIFS: Add capability to decrypt big read responses
CIFS: Decrypt and process small encrypted packets
CIFS: Add copy into pages callback for a read operation
CIFS: Add mid handle callback
CIFS: Add transform header handling callbacks
CIFS: Encrypt SMB3 requests before sending
CIFS: Enable encryption during session setup phase
CIFS: Add capability to transform requests before sending
CIFS: Separate RFC1001 length processing for SMB2 read
CIFS: Separate SMB2 sync header processing
CIFS: Send RFC1001 length in a separate iov
CIFS: Make send_cancel take rqst as argument
CIFS: Make SendReceive2() takes resp iov
CIFS: Separate SMB2 header structure
CIFS: Fix splice read for non-cached files
cifs: Add soft dependencies
cifs: Only select the required crypto modules
cifs: Simplify SMB2 and SMB311 dependencies
-rw-r--r-- | fs/cifs/Kconfig | 12 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 51 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 14 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 28 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 135 | ||||
-rw-r--r-- | fs/cifs/connect.c | 71 | ||||
-rw-r--r-- | fs/cifs/file.c | 62 | ||||
-rw-r--r-- | fs/cifs/sess.c | 27 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 4 | ||||
-rw-r--r-- | fs/cifs/smb2glob.h | 5 | ||||
-rw-r--r-- | fs/cifs/smb2maperror.c | 5 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 61 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 663 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 575 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 27 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 5 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 132 | ||||
-rw-r--r-- | fs/cifs/transport.c | 171 |
19 files changed, 1582 insertions, 479 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index e7b478b49985..034f00f21390 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -9,8 +9,6 @@ config CIFS | |||
9 | select CRYPTO_ARC4 | 9 | select CRYPTO_ARC4 |
10 | select CRYPTO_ECB | 10 | select CRYPTO_ECB |
11 | select CRYPTO_DES | 11 | select CRYPTO_DES |
12 | select CRYPTO_SHA256 | ||
13 | select CRYPTO_CMAC | ||
14 | help | 12 | help |
15 | This is the client VFS module for the Common Internet File System | 13 | This is the client VFS module for the Common Internet File System |
16 | (CIFS) protocol which is the successor to the Server Message Block | 14 | (CIFS) protocol which is the successor to the Server Message Block |
@@ -169,11 +167,15 @@ config CIFS_NFSD_EXPORT | |||
169 | 167 | ||
170 | config CIFS_SMB2 | 168 | config CIFS_SMB2 |
171 | bool "SMB2 and SMB3 network file system support" | 169 | bool "SMB2 and SMB3 network file system support" |
172 | depends on CIFS && INET | 170 | depends on CIFS |
173 | select NLS | ||
174 | select KEYS | 171 | select KEYS |
175 | select FSCACHE | 172 | select FSCACHE |
176 | select DNS_RESOLVER | 173 | select DNS_RESOLVER |
174 | select CRYPTO_AES | ||
175 | select CRYPTO_SHA256 | ||
176 | select CRYPTO_CMAC | ||
177 | select CRYPTO_AEAD2 | ||
178 | select CRYPTO_CCM | ||
177 | 179 | ||
178 | help | 180 | help |
179 | This enables support for the Server Message Block version 2 | 181 | This enables support for the Server Message Block version 2 |
@@ -194,7 +196,7 @@ config CIFS_SMB2 | |||
194 | 196 | ||
195 | config CIFS_SMB311 | 197 | config CIFS_SMB311 |
196 | bool "SMB3.1.1 network file system support (Experimental)" | 198 | bool "SMB3.1.1 network file system support (Experimental)" |
197 | depends on CIFS_SMB2 && INET | 199 | depends on CIFS_SMB2 |
198 | 200 | ||
199 | help | 201 | help |
200 | This enables experimental support for the newest, SMB3.1.1, dialect. | 202 | This enables experimental support for the newest, SMB3.1.1, dialect. |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 66bd7fa9b7a6..058ac9b36f04 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/random.h> | 34 | #include <linux/random.h> |
35 | #include <linux/highmem.h> | 35 | #include <linux/highmem.h> |
36 | #include <crypto/skcipher.h> | 36 | #include <crypto/skcipher.h> |
37 | #include <crypto/aead.h> | ||
37 | 38 | ||
38 | static int | 39 | static int |
39 | cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) | 40 | cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) |
@@ -75,24 +76,20 @@ int __cifs_calc_signature(struct smb_rqst *rqst, | |||
75 | struct kvec *iov = rqst->rq_iov; | 76 | struct kvec *iov = rqst->rq_iov; |
76 | int n_vec = rqst->rq_nvec; | 77 | int n_vec = rqst->rq_nvec; |
77 | 78 | ||
78 | for (i = 0; i < n_vec; i++) { | 79 | if (n_vec < 2 || iov[0].iov_len != 4) |
80 | return -EIO; | ||
81 | |||
82 | for (i = 1; i < n_vec; i++) { | ||
79 | if (iov[i].iov_len == 0) | 83 | if (iov[i].iov_len == 0) |
80 | continue; | 84 | continue; |
81 | if (iov[i].iov_base == NULL) { | 85 | if (iov[i].iov_base == NULL) { |
82 | cifs_dbg(VFS, "null iovec entry\n"); | 86 | cifs_dbg(VFS, "null iovec entry\n"); |
83 | return -EIO; | 87 | return -EIO; |
84 | } | 88 | } |
85 | /* The first entry includes a length field (which does not get | 89 | if (i == 1 && iov[1].iov_len <= 4) |
86 | signed that occupies the first 4 bytes before the header */ | 90 | break; /* nothing to sign or corrupt header */ |
87 | if (i == 0) { | 91 | rc = crypto_shash_update(shash, |
88 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ | 92 | iov[i].iov_base, iov[i].iov_len); |
89 | break; /* nothing to sign or corrupt header */ | ||
90 | rc = crypto_shash_update(shash, | ||
91 | iov[i].iov_base + 4, iov[i].iov_len - 4); | ||
92 | } else { | ||
93 | rc = crypto_shash_update(shash, | ||
94 | iov[i].iov_base, iov[i].iov_len); | ||
95 | } | ||
96 | if (rc) { | 93 | if (rc) { |
97 | cifs_dbg(VFS, "%s: Could not update with payload\n", | 94 | cifs_dbg(VFS, "%s: Could not update with payload\n", |
98 | __func__); | 95 | __func__); |
@@ -168,6 +165,10 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, | |||
168 | char smb_signature[20]; | 165 | char smb_signature[20]; |
169 | struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; | 166 | struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; |
170 | 167 | ||
168 | if (rqst->rq_iov[0].iov_len != 4 || | ||
169 | rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) | ||
170 | return -EIO; | ||
171 | |||
171 | if ((cifs_pdu == NULL) || (server == NULL)) | 172 | if ((cifs_pdu == NULL) || (server == NULL)) |
172 | return -EINVAL; | 173 | return -EINVAL; |
173 | 174 | ||
@@ -209,12 +210,14 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
209 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 210 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, |
210 | __u32 *pexpected_response_sequence_number) | 211 | __u32 *pexpected_response_sequence_number) |
211 | { | 212 | { |
212 | struct kvec iov; | 213 | struct kvec iov[2]; |
213 | 214 | ||
214 | iov.iov_base = cifs_pdu; | 215 | iov[0].iov_base = cifs_pdu; |
215 | iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; | 216 | iov[0].iov_len = 4; |
217 | iov[1].iov_base = (char *)cifs_pdu + 4; | ||
218 | iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length); | ||
216 | 219 | ||
217 | return cifs_sign_smbv(&iov, 1, server, | 220 | return cifs_sign_smbv(iov, 2, server, |
218 | pexpected_response_sequence_number); | 221 | pexpected_response_sequence_number); |
219 | } | 222 | } |
220 | 223 | ||
@@ -227,6 +230,10 @@ int cifs_verify_signature(struct smb_rqst *rqst, | |||
227 | char what_we_think_sig_should_be[20]; | 230 | char what_we_think_sig_should_be[20]; |
228 | struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; | 231 | struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base; |
229 | 232 | ||
233 | if (rqst->rq_iov[0].iov_len != 4 || | ||
234 | rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) | ||
235 | return -EIO; | ||
236 | |||
230 | if (cifs_pdu == NULL || server == NULL) | 237 | if (cifs_pdu == NULL || server == NULL) |
231 | return -EINVAL; | 238 | return -EINVAL; |
232 | 239 | ||
@@ -868,7 +875,7 @@ out: | |||
868 | } | 875 | } |
869 | 876 | ||
870 | void | 877 | void |
871 | cifs_crypto_shash_release(struct TCP_Server_Info *server) | 878 | cifs_crypto_secmech_release(struct TCP_Server_Info *server) |
872 | { | 879 | { |
873 | if (server->secmech.cmacaes) { | 880 | if (server->secmech.cmacaes) { |
874 | crypto_free_shash(server->secmech.cmacaes); | 881 | crypto_free_shash(server->secmech.cmacaes); |
@@ -890,6 +897,16 @@ cifs_crypto_shash_release(struct TCP_Server_Info *server) | |||
890 | server->secmech.hmacmd5 = NULL; | 897 | server->secmech.hmacmd5 = NULL; |
891 | } | 898 | } |
892 | 899 | ||
900 | if (server->secmech.ccmaesencrypt) { | ||
901 | crypto_free_aead(server->secmech.ccmaesencrypt); | ||
902 | server->secmech.ccmaesencrypt = NULL; | ||
903 | } | ||
904 | |||
905 | if (server->secmech.ccmaesdecrypt) { | ||
906 | crypto_free_aead(server->secmech.ccmaesdecrypt); | ||
907 | server->secmech.ccmaesdecrypt = NULL; | ||
908 | } | ||
909 | |||
893 | kfree(server->secmech.sdesccmacaes); | 910 | kfree(server->secmech.sdesccmacaes); |
894 | server->secmech.sdesccmacaes = NULL; | 911 | server->secmech.sdesccmacaes = NULL; |
895 | kfree(server->secmech.sdeschmacsha256); | 912 | kfree(server->secmech.sdeschmacsha256); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 70f4e65fced2..15e1db8738ae 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -1365,5 +1365,19 @@ MODULE_DESCRIPTION | |||
1365 | ("VFS to access servers complying with the SNIA CIFS Specification " | 1365 | ("VFS to access servers complying with the SNIA CIFS Specification " |
1366 | "e.g. Samba and Windows"); | 1366 | "e.g. Samba and Windows"); |
1367 | MODULE_VERSION(CIFS_VERSION); | 1367 | MODULE_VERSION(CIFS_VERSION); |
1368 | MODULE_SOFTDEP("pre: arc4"); | ||
1369 | MODULE_SOFTDEP("pre: des"); | ||
1370 | MODULE_SOFTDEP("pre: ecb"); | ||
1371 | MODULE_SOFTDEP("pre: hmac"); | ||
1372 | MODULE_SOFTDEP("pre: md4"); | ||
1373 | MODULE_SOFTDEP("pre: md5"); | ||
1374 | MODULE_SOFTDEP("pre: nls"); | ||
1375 | #ifdef CONFIG_CIFS_SMB2 | ||
1376 | MODULE_SOFTDEP("pre: aes"); | ||
1377 | MODULE_SOFTDEP("pre: cmac"); | ||
1378 | MODULE_SOFTDEP("pre: sha256"); | ||
1379 | MODULE_SOFTDEP("pre: aead2"); | ||
1380 | MODULE_SOFTDEP("pre: ccm"); | ||
1381 | #endif /* CONFIG_CIFS_SMB2 */ | ||
1368 | module_init(init_cifs) | 1382 | module_init(init_cifs) |
1369 | module_exit(exit_cifs) | 1383 | module_exit(exit_cifs) |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7ea8a3393936..1a90bb3e2986 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -136,6 +136,8 @@ struct cifs_secmech { | |||
136 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ | 136 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ |
137 | struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */ | 137 | struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */ |
138 | struct sdesc *sdesccmacaes; /* ctxt to generate smb3 signature */ | 138 | struct sdesc *sdesccmacaes; /* ctxt to generate smb3 signature */ |
139 | struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */ | ||
140 | struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */ | ||
139 | }; | 141 | }; |
140 | 142 | ||
141 | /* per smb session structure/fields */ | 143 | /* per smb session structure/fields */ |
@@ -208,7 +210,7 @@ struct cifsInodeInfo; | |||
208 | struct cifs_open_parms; | 210 | struct cifs_open_parms; |
209 | 211 | ||
210 | struct smb_version_operations { | 212 | struct smb_version_operations { |
211 | int (*send_cancel)(struct TCP_Server_Info *, void *, | 213 | int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *, |
212 | struct mid_q_entry *); | 214 | struct mid_q_entry *); |
213 | bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *); | 215 | bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *); |
214 | /* setup request: allocate mid, sign message */ | 216 | /* setup request: allocate mid, sign message */ |
@@ -433,6 +435,14 @@ struct smb_version_operations { | |||
433 | bool (*dir_needs_close)(struct cifsFileInfo *); | 435 | bool (*dir_needs_close)(struct cifsFileInfo *); |
434 | long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, | 436 | long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, |
435 | loff_t); | 437 | loff_t); |
438 | /* init transform request - used for encryption for now */ | ||
439 | int (*init_transform_rq)(struct TCP_Server_Info *, struct smb_rqst *, | ||
440 | struct smb_rqst *); | ||
441 | /* free transform request */ | ||
442 | void (*free_transform_rq)(struct smb_rqst *); | ||
443 | int (*is_transform_hdr)(void *buf); | ||
444 | int (*receive_transform)(struct TCP_Server_Info *, | ||
445 | struct mid_q_entry **); | ||
436 | }; | 446 | }; |
437 | 447 | ||
438 | struct smb_version_values { | 448 | struct smb_version_values { |
@@ -1119,7 +1129,10 @@ struct cifs_readdata { | |||
1119 | int (*read_into_pages)(struct TCP_Server_Info *server, | 1129 | int (*read_into_pages)(struct TCP_Server_Info *server, |
1120 | struct cifs_readdata *rdata, | 1130 | struct cifs_readdata *rdata, |
1121 | unsigned int len); | 1131 | unsigned int len); |
1122 | struct kvec iov; | 1132 | int (*copy_into_pages)(struct TCP_Server_Info *server, |
1133 | struct cifs_readdata *rdata, | ||
1134 | struct iov_iter *iter); | ||
1135 | struct kvec iov[2]; | ||
1123 | unsigned int pagesz; | 1136 | unsigned int pagesz; |
1124 | unsigned int tailsz; | 1137 | unsigned int tailsz; |
1125 | unsigned int credits; | 1138 | unsigned int credits; |
@@ -1302,6 +1315,13 @@ typedef int (mid_receive_t)(struct TCP_Server_Info *server, | |||
1302 | */ | 1315 | */ |
1303 | typedef void (mid_callback_t)(struct mid_q_entry *mid); | 1316 | typedef void (mid_callback_t)(struct mid_q_entry *mid); |
1304 | 1317 | ||
1318 | /* | ||
1319 | * This is the protopyte for mid handle function. This is called once the mid | ||
1320 | * has been recognized after decryption of the message. | ||
1321 | */ | ||
1322 | typedef int (mid_handle_t)(struct TCP_Server_Info *server, | ||
1323 | struct mid_q_entry *mid); | ||
1324 | |||
1305 | /* one of these for every pending CIFS request to the server */ | 1325 | /* one of these for every pending CIFS request to the server */ |
1306 | struct mid_q_entry { | 1326 | struct mid_q_entry { |
1307 | struct list_head qhead; /* mids waiting on reply from this server */ | 1327 | struct list_head qhead; /* mids waiting on reply from this server */ |
@@ -1316,6 +1336,7 @@ struct mid_q_entry { | |||
1316 | #endif | 1336 | #endif |
1317 | mid_receive_t *receive; /* call receive callback */ | 1337 | mid_receive_t *receive; /* call receive callback */ |
1318 | mid_callback_t *callback; /* call completion callback */ | 1338 | mid_callback_t *callback; /* call completion callback */ |
1339 | mid_handle_t *handle; /* call handle mid callback */ | ||
1319 | void *callback_data; /* general purpose pointer for callback */ | 1340 | void *callback_data; /* general purpose pointer for callback */ |
1320 | void *resp_buf; /* pointer to received SMB header */ | 1341 | void *resp_buf; /* pointer to received SMB header */ |
1321 | int mid_state; /* wish this were enum but can not pass to wait_event */ | 1342 | int mid_state; /* wish this were enum but can not pass to wait_event */ |
@@ -1323,6 +1344,7 @@ struct mid_q_entry { | |||
1323 | bool large_buf:1; /* if valid response, is pointer to large buf */ | 1344 | bool large_buf:1; /* if valid response, is pointer to large buf */ |
1324 | bool multiRsp:1; /* multiple trans2 responses for one request */ | 1345 | bool multiRsp:1; /* multiple trans2 responses for one request */ |
1325 | bool multiEnd:1; /* both received */ | 1346 | bool multiEnd:1; /* both received */ |
1347 | bool decrypted:1; /* decrypted entry */ | ||
1326 | }; | 1348 | }; |
1327 | 1349 | ||
1328 | /* Make code in transport.c a little cleaner by moving | 1350 | /* Make code in transport.c a little cleaner by moving |
@@ -1475,7 +1497,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, | |||
1475 | #define CIFS_OBREAK_OP 0x0100 /* oplock break request */ | 1497 | #define CIFS_OBREAK_OP 0x0100 /* oplock break request */ |
1476 | #define CIFS_NEG_OP 0x0200 /* negotiate request */ | 1498 | #define CIFS_NEG_OP 0x0200 /* negotiate request */ |
1477 | #define CIFS_OP_MASK 0x0380 /* mask request type */ | 1499 | #define CIFS_OP_MASK 0x0380 /* mask request type */ |
1500 | |||
1478 | #define CIFS_HAS_CREDITS 0x0400 /* already has credits */ | 1501 | #define CIFS_HAS_CREDITS 0x0400 /* already has credits */ |
1502 | #define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */ | ||
1479 | 1503 | ||
1480 | /* Security Flags: indicate type of session setup needed */ | 1504 | /* Security Flags: indicate type of session setup needed */ |
1481 | #define CIFSSEC_MAY_SIGN 0x00001 | 1505 | #define CIFSSEC_MAY_SIGN 0x00001 |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c7b3c841e660..406d2c10ba78 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -75,10 +75,16 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, | |||
75 | extern void DeleteMidQEntry(struct mid_q_entry *midEntry); | 75 | extern void DeleteMidQEntry(struct mid_q_entry *midEntry); |
76 | extern void cifs_delete_mid(struct mid_q_entry *mid); | 76 | extern void cifs_delete_mid(struct mid_q_entry *mid); |
77 | extern void cifs_wake_up_task(struct mid_q_entry *mid); | 77 | extern void cifs_wake_up_task(struct mid_q_entry *mid); |
78 | extern int cifs_handle_standard(struct TCP_Server_Info *server, | ||
79 | struct mid_q_entry *mid); | ||
80 | extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); | ||
78 | extern int cifs_call_async(struct TCP_Server_Info *server, | 81 | extern int cifs_call_async(struct TCP_Server_Info *server, |
79 | struct smb_rqst *rqst, | 82 | struct smb_rqst *rqst, |
80 | mid_receive_t *receive, mid_callback_t *callback, | 83 | mid_receive_t *receive, mid_callback_t *callback, |
81 | void *cbdata, const int flags); | 84 | mid_handle_t *handle, void *cbdata, const int flags); |
85 | extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, | ||
86 | struct smb_rqst *rqst, int *resp_buf_type, | ||
87 | const int flags, struct kvec *resp_iov); | ||
82 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, | 88 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, |
83 | struct smb_hdr * /* input */ , | 89 | struct smb_hdr * /* input */ , |
84 | struct smb_hdr * /* out */ , | 90 | struct smb_hdr * /* out */ , |
@@ -96,7 +102,8 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server, | |||
96 | unsigned int *credits); | 102 | unsigned int *credits); |
97 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, | 103 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, |
98 | struct kvec *, int /* nvec to send */, | 104 | struct kvec *, int /* nvec to send */, |
99 | int * /* type of buf returned */ , const int flags); | 105 | int * /* type of buf returned */, const int flags, |
106 | struct kvec * /* resp vec */); | ||
100 | extern int SendReceiveBlockingLock(const unsigned int xid, | 107 | extern int SendReceiveBlockingLock(const unsigned int xid, |
101 | struct cifs_tcon *ptcon, | 108 | struct cifs_tcon *ptcon, |
102 | struct smb_hdr *in_buf , | 109 | struct smb_hdr *in_buf , |
@@ -441,7 +448,7 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, | |||
441 | const struct nls_table *); | 448 | const struct nls_table *); |
442 | extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); | 449 | extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); |
443 | extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); | 450 | extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); |
444 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | 451 | extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server); |
445 | extern int calc_seckey(struct cifs_ses *); | 452 | extern int calc_seckey(struct cifs_ses *); |
446 | extern int generate_smb30signingkey(struct cifs_ses *); | 453 | extern int generate_smb30signingkey(struct cifs_ses *); |
447 | extern int generate_smb311signingkey(struct cifs_ses *); | 454 | extern int generate_smb311signingkey(struct cifs_ses *); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b47261858e6d..f5099fb8a22f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -673,6 +673,7 @@ CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon) | |||
673 | return rc; | 673 | return rc; |
674 | 674 | ||
675 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); | 675 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); |
676 | cifs_small_buf_release(smb_buffer); | ||
676 | if (rc) | 677 | if (rc) |
677 | cifs_dbg(FYI, "Tree disconnect failed %d\n", rc); | 678 | cifs_dbg(FYI, "Tree disconnect failed %d\n", rc); |
678 | 679 | ||
@@ -707,9 +708,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
707 | { | 708 | { |
708 | ECHO_REQ *smb; | 709 | ECHO_REQ *smb; |
709 | int rc = 0; | 710 | int rc = 0; |
710 | struct kvec iov; | 711 | struct kvec iov[2]; |
711 | struct smb_rqst rqst = { .rq_iov = &iov, | 712 | struct smb_rqst rqst = { .rq_iov = iov, |
712 | .rq_nvec = 1 }; | 713 | .rq_nvec = 2 }; |
713 | 714 | ||
714 | cifs_dbg(FYI, "In echo request\n"); | 715 | cifs_dbg(FYI, "In echo request\n"); |
715 | 716 | ||
@@ -724,10 +725,13 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
724 | put_bcc(1, &smb->hdr); | 725 | put_bcc(1, &smb->hdr); |
725 | smb->Data[0] = 'a'; | 726 | smb->Data[0] = 'a'; |
726 | inc_rfc1001_len(smb, 3); | 727 | inc_rfc1001_len(smb, 3); |
727 | iov.iov_base = smb; | ||
728 | iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; | ||
729 | 728 | ||
730 | rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, | 729 | iov[0].iov_len = 4; |
730 | iov[0].iov_base = smb; | ||
731 | iov[1].iov_len = get_rfc1002_length(smb); | ||
732 | iov[1].iov_base = (char *)smb + 4; | ||
733 | |||
734 | rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL, | ||
731 | server, CIFS_ASYNC_OP | CIFS_ECHO_OP); | 735 | server, CIFS_ASYNC_OP | CIFS_ECHO_OP); |
732 | if (rc) | 736 | if (rc) |
733 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); | 737 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); |
@@ -772,6 +776,7 @@ CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses) | |||
772 | 776 | ||
773 | pSMB->AndXCommand = 0xFF; | 777 | pSMB->AndXCommand = 0xFF; |
774 | rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); | 778 | rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); |
779 | cifs_small_buf_release(pSMB); | ||
775 | session_already_dead: | 780 | session_already_dead: |
776 | mutex_unlock(&ses->session_mutex); | 781 | mutex_unlock(&ses->session_mutex); |
777 | 782 | ||
@@ -1394,8 +1399,8 @@ openRetry: | |||
1394 | * Discard any remaining data in the current SMB. To do this, we borrow the | 1399 | * Discard any remaining data in the current SMB. To do this, we borrow the |
1395 | * current bigbuf. | 1400 | * current bigbuf. |
1396 | */ | 1401 | */ |
1397 | static int | 1402 | int |
1398 | discard_remaining_data(struct TCP_Server_Info *server) | 1403 | cifs_discard_remaining_data(struct TCP_Server_Info *server) |
1399 | { | 1404 | { |
1400 | unsigned int rfclen = get_rfc1002_length(server->smallbuf); | 1405 | unsigned int rfclen = get_rfc1002_length(server->smallbuf); |
1401 | int remaining = rfclen + 4 - server->total_read; | 1406 | int remaining = rfclen + 4 - server->total_read; |
@@ -1421,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1421 | int length; | 1426 | int length; |
1422 | struct cifs_readdata *rdata = mid->callback_data; | 1427 | struct cifs_readdata *rdata = mid->callback_data; |
1423 | 1428 | ||
1424 | length = discard_remaining_data(server); | 1429 | length = cifs_discard_remaining_data(server); |
1425 | dequeue_mid(mid, rdata->result); | 1430 | dequeue_mid(mid, rdata->result); |
1426 | return length; | 1431 | return length; |
1427 | } | 1432 | } |
@@ -1454,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1454 | 1459 | ||
1455 | if (server->ops->is_status_pending && | 1460 | if (server->ops->is_status_pending && |
1456 | server->ops->is_status_pending(buf, server, 0)) { | 1461 | server->ops->is_status_pending(buf, server, 0)) { |
1457 | discard_remaining_data(server); | 1462 | cifs_discard_remaining_data(server); |
1458 | return -1; | 1463 | return -1; |
1459 | } | 1464 | } |
1460 | 1465 | ||
@@ -1507,10 +1512,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1507 | } | 1512 | } |
1508 | 1513 | ||
1509 | /* set up first iov for signature check */ | 1514 | /* set up first iov for signature check */ |
1510 | rdata->iov.iov_base = buf; | 1515 | rdata->iov[0].iov_base = buf; |
1511 | rdata->iov.iov_len = server->total_read; | 1516 | rdata->iov[0].iov_len = 4; |
1512 | cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", | 1517 | rdata->iov[1].iov_base = buf + 4; |
1513 | rdata->iov.iov_base, rdata->iov.iov_len); | 1518 | rdata->iov[1].iov_len = server->total_read - 4; |
1519 | cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", | ||
1520 | rdata->iov[0].iov_base, server->total_read); | ||
1514 | 1521 | ||
1515 | /* how much data is in the response? */ | 1522 | /* how much data is in the response? */ |
1516 | data_len = server->ops->read_data_length(buf); | 1523 | data_len = server->ops->read_data_length(buf); |
@@ -1543,8 +1550,8 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1543 | struct cifs_readdata *rdata = mid->callback_data; | 1550 | struct cifs_readdata *rdata = mid->callback_data; |
1544 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | 1551 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
1545 | struct TCP_Server_Info *server = tcon->ses->server; | 1552 | struct TCP_Server_Info *server = tcon->ses->server; |
1546 | struct smb_rqst rqst = { .rq_iov = &rdata->iov, | 1553 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
1547 | .rq_nvec = 1, | 1554 | .rq_nvec = 2, |
1548 | .rq_pages = rdata->pages, | 1555 | .rq_pages = rdata->pages, |
1549 | .rq_npages = rdata->nr_pages, | 1556 | .rq_npages = rdata->nr_pages, |
1550 | .rq_pagesz = rdata->pagesz, | 1557 | .rq_pagesz = rdata->pagesz, |
@@ -1599,8 +1606,8 @@ cifs_async_readv(struct cifs_readdata *rdata) | |||
1599 | READ_REQ *smb = NULL; | 1606 | READ_REQ *smb = NULL; |
1600 | int wct; | 1607 | int wct; |
1601 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | 1608 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
1602 | struct smb_rqst rqst = { .rq_iov = &rdata->iov, | 1609 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
1603 | .rq_nvec = 1 }; | 1610 | .rq_nvec = 2 }; |
1604 | 1611 | ||
1605 | cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", | 1612 | cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", |
1606 | __func__, rdata->offset, rdata->bytes); | 1613 | __func__, rdata->offset, rdata->bytes); |
@@ -1640,12 +1647,14 @@ cifs_async_readv(struct cifs_readdata *rdata) | |||
1640 | } | 1647 | } |
1641 | 1648 | ||
1642 | /* 4 for RFC1001 length + 1 for BCC */ | 1649 | /* 4 for RFC1001 length + 1 for BCC */ |
1643 | rdata->iov.iov_base = smb; | 1650 | rdata->iov[0].iov_base = smb; |
1644 | rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; | 1651 | rdata->iov[0].iov_len = 4; |
1652 | rdata->iov[1].iov_base = (char *)smb + 4; | ||
1653 | rdata->iov[1].iov_len = get_rfc1002_length(smb); | ||
1645 | 1654 | ||
1646 | kref_get(&rdata->refcount); | 1655 | kref_get(&rdata->refcount); |
1647 | rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, | 1656 | rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, |
1648 | cifs_readv_callback, rdata, 0); | 1657 | cifs_readv_callback, NULL, rdata, 0); |
1649 | 1658 | ||
1650 | if (rc == 0) | 1659 | if (rc == 0) |
1651 | cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); | 1660 | cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); |
@@ -1667,6 +1676,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
1667 | int wct; | 1676 | int wct; |
1668 | int resp_buf_type = 0; | 1677 | int resp_buf_type = 0; |
1669 | struct kvec iov[1]; | 1678 | struct kvec iov[1]; |
1679 | struct kvec rsp_iov; | ||
1670 | __u32 pid = io_parms->pid; | 1680 | __u32 pid = io_parms->pid; |
1671 | __u16 netfid = io_parms->netfid; | 1681 | __u16 netfid = io_parms->netfid; |
1672 | __u64 offset = io_parms->offset; | 1682 | __u64 offset = io_parms->offset; |
@@ -1716,10 +1726,11 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
1716 | 1726 | ||
1717 | iov[0].iov_base = (char *)pSMB; | 1727 | iov[0].iov_base = (char *)pSMB; |
1718 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; | 1728 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1719 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1729 | rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type, |
1720 | &resp_buf_type, CIFS_LOG_ERROR); | 1730 | CIFS_LOG_ERROR, &rsp_iov); |
1731 | cifs_small_buf_release(pSMB); | ||
1721 | cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); | 1732 | cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); |
1722 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1733 | pSMBr = (READ_RSP *)rsp_iov.iov_base; |
1723 | if (rc) { | 1734 | if (rc) { |
1724 | cifs_dbg(VFS, "Send error in read = %d\n", rc); | 1735 | cifs_dbg(VFS, "Send error in read = %d\n", rc); |
1725 | } else { | 1736 | } else { |
@@ -1747,12 +1758,11 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
1747 | } | 1758 | } |
1748 | } | 1759 | } |
1749 | 1760 | ||
1750 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | ||
1751 | if (*buf) { | 1761 | if (*buf) { |
1752 | free_rsp_buf(resp_buf_type, iov[0].iov_base); | 1762 | free_rsp_buf(resp_buf_type, rsp_iov.iov_base); |
1753 | } else if (resp_buf_type != CIFS_NO_BUFFER) { | 1763 | } else if (resp_buf_type != CIFS_NO_BUFFER) { |
1754 | /* return buffer to caller to free */ | 1764 | /* return buffer to caller to free */ |
1755 | *buf = iov[0].iov_base; | 1765 | *buf = rsp_iov.iov_base; |
1756 | if (resp_buf_type == CIFS_SMALL_BUFFER) | 1766 | if (resp_buf_type == CIFS_SMALL_BUFFER) |
1757 | *pbuf_type = CIFS_SMALL_BUFFER; | 1767 | *pbuf_type = CIFS_SMALL_BUFFER; |
1758 | else if (resp_buf_type == CIFS_LARGE_BUFFER) | 1768 | else if (resp_buf_type == CIFS_LARGE_BUFFER) |
@@ -2093,7 +2103,7 @@ cifs_async_writev(struct cifs_writedata *wdata, | |||
2093 | WRITE_REQ *smb = NULL; | 2103 | WRITE_REQ *smb = NULL; |
2094 | int wct; | 2104 | int wct; |
2095 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | 2105 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
2096 | struct kvec iov; | 2106 | struct kvec iov[2]; |
2097 | struct smb_rqst rqst = { }; | 2107 | struct smb_rqst rqst = { }; |
2098 | 2108 | ||
2099 | if (tcon->ses->capabilities & CAP_LARGE_FILES) { | 2109 | if (tcon->ses->capabilities & CAP_LARGE_FILES) { |
@@ -2126,11 +2136,13 @@ cifs_async_writev(struct cifs_writedata *wdata, | |||
2126 | cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); | 2136 | cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); |
2127 | 2137 | ||
2128 | /* 4 for RFC1001 length + 1 for BCC */ | 2138 | /* 4 for RFC1001 length + 1 for BCC */ |
2129 | iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; | 2139 | iov[0].iov_len = 4; |
2130 | iov.iov_base = smb; | 2140 | iov[0].iov_base = smb; |
2141 | iov[1].iov_len = get_rfc1002_length(smb) + 1; | ||
2142 | iov[1].iov_base = (char *)smb + 4; | ||
2131 | 2143 | ||
2132 | rqst.rq_iov = &iov; | 2144 | rqst.rq_iov = iov; |
2133 | rqst.rq_nvec = 1; | 2145 | rqst.rq_nvec = 2; |
2134 | rqst.rq_pages = wdata->pages; | 2146 | rqst.rq_pages = wdata->pages; |
2135 | rqst.rq_npages = wdata->nr_pages; | 2147 | rqst.rq_npages = wdata->nr_pages; |
2136 | rqst.rq_pagesz = wdata->pagesz; | 2148 | rqst.rq_pagesz = wdata->pagesz; |
@@ -2151,12 +2163,12 @@ cifs_async_writev(struct cifs_writedata *wdata, | |||
2151 | (struct smb_com_writex_req *)smb; | 2163 | (struct smb_com_writex_req *)smb; |
2152 | inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); | 2164 | inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); |
2153 | put_bcc(wdata->bytes + 5, &smbw->hdr); | 2165 | put_bcc(wdata->bytes + 5, &smbw->hdr); |
2154 | iov.iov_len += 4; /* pad bigger by four bytes */ | 2166 | iov[1].iov_len += 4; /* pad bigger by four bytes */ |
2155 | } | 2167 | } |
2156 | 2168 | ||
2157 | kref_get(&wdata->refcount); | 2169 | kref_get(&wdata->refcount); |
2158 | rc = cifs_call_async(tcon->ses->server, &rqst, NULL, | 2170 | rc = cifs_call_async(tcon->ses->server, &rqst, NULL, |
2159 | cifs_writev_callback, wdata, 0); | 2171 | cifs_writev_callback, NULL, wdata, 0); |
2160 | 2172 | ||
2161 | if (rc == 0) | 2173 | if (rc == 0) |
2162 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); | 2174 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); |
@@ -2182,6 +2194,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2182 | __u64 offset = io_parms->offset; | 2194 | __u64 offset = io_parms->offset; |
2183 | struct cifs_tcon *tcon = io_parms->tcon; | 2195 | struct cifs_tcon *tcon = io_parms->tcon; |
2184 | unsigned int count = io_parms->length; | 2196 | unsigned int count = io_parms->length; |
2197 | struct kvec rsp_iov; | ||
2185 | 2198 | ||
2186 | *nbytes = 0; | 2199 | *nbytes = 0; |
2187 | 2200 | ||
@@ -2240,8 +2253,9 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2240 | else /* wct == 12 pad bigger by four bytes */ | 2253 | else /* wct == 12 pad bigger by four bytes */ |
2241 | iov[0].iov_len = smb_hdr_len + 8; | 2254 | iov[0].iov_len = smb_hdr_len + 8; |
2242 | 2255 | ||
2243 | 2256 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0, | |
2244 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0); | 2257 | &rsp_iov); |
2258 | cifs_small_buf_release(pSMB); | ||
2245 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); | 2259 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); |
2246 | if (rc) { | 2260 | if (rc) { |
2247 | cifs_dbg(FYI, "Send error Write2 = %d\n", rc); | 2261 | cifs_dbg(FYI, "Send error Write2 = %d\n", rc); |
@@ -2249,7 +2263,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2249 | /* presumably this can not happen, but best to be safe */ | 2263 | /* presumably this can not happen, but best to be safe */ |
2250 | rc = -EIO; | 2264 | rc = -EIO; |
2251 | } else { | 2265 | } else { |
2252 | WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; | 2266 | WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base; |
2253 | *nbytes = le16_to_cpu(pSMBr->CountHigh); | 2267 | *nbytes = le16_to_cpu(pSMBr->CountHigh); |
2254 | *nbytes = (*nbytes) << 16; | 2268 | *nbytes = (*nbytes) << 16; |
2255 | *nbytes += le16_to_cpu(pSMBr->Count); | 2269 | *nbytes += le16_to_cpu(pSMBr->Count); |
@@ -2263,8 +2277,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2263 | *nbytes &= 0xFFFF; | 2277 | *nbytes &= 0xFFFF; |
2264 | } | 2278 | } |
2265 | 2279 | ||
2266 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | 2280 | free_rsp_buf(resp_buf_type, rsp_iov.iov_base); |
2267 | free_rsp_buf(resp_buf_type, iov[0].iov_base); | ||
2268 | 2281 | ||
2269 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 2282 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
2270 | since file handle passed in no longer valid */ | 2283 | since file handle passed in no longer valid */ |
@@ -2279,6 +2292,7 @@ int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
2279 | int rc = 0; | 2292 | int rc = 0; |
2280 | LOCK_REQ *pSMB = NULL; | 2293 | LOCK_REQ *pSMB = NULL; |
2281 | struct kvec iov[2]; | 2294 | struct kvec iov[2]; |
2295 | struct kvec rsp_iov; | ||
2282 | int resp_buf_type; | 2296 | int resp_buf_type; |
2283 | __u16 count; | 2297 | __u16 count; |
2284 | 2298 | ||
@@ -2307,7 +2321,9 @@ int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
2307 | iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); | 2321 | iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); |
2308 | 2322 | ||
2309 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); | 2323 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); |
2310 | rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP); | 2324 | rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP, |
2325 | &rsp_iov); | ||
2326 | cifs_small_buf_release(pSMB); | ||
2311 | if (rc) | 2327 | if (rc) |
2312 | cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc); | 2328 | cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc); |
2313 | 2329 | ||
@@ -2368,14 +2384,12 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
2368 | inc_rfc1001_len(pSMB, count); | 2384 | inc_rfc1001_len(pSMB, count); |
2369 | pSMB->ByteCount = cpu_to_le16(count); | 2385 | pSMB->ByteCount = cpu_to_le16(count); |
2370 | 2386 | ||
2371 | if (waitFlag) { | 2387 | if (waitFlag) |
2372 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 2388 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
2373 | (struct smb_hdr *) pSMB, &bytes_returned); | 2389 | (struct smb_hdr *) pSMB, &bytes_returned); |
2374 | cifs_small_buf_release(pSMB); | 2390 | else |
2375 | } else { | ||
2376 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags); | 2391 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags); |
2377 | /* SMB buffer freed by function above */ | 2392 | cifs_small_buf_release(pSMB); |
2378 | } | ||
2379 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); | 2393 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); |
2380 | if (rc) | 2394 | if (rc) |
2381 | cifs_dbg(FYI, "Send error in Lock = %d\n", rc); | 2395 | cifs_dbg(FYI, "Send error in Lock = %d\n", rc); |
@@ -2401,6 +2415,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
2401 | int resp_buf_type = 0; | 2415 | int resp_buf_type = 0; |
2402 | __u16 params, param_offset, offset, byte_count, count; | 2416 | __u16 params, param_offset, offset, byte_count, count; |
2403 | struct kvec iov[1]; | 2417 | struct kvec iov[1]; |
2418 | struct kvec rsp_iov; | ||
2404 | 2419 | ||
2405 | cifs_dbg(FYI, "Posix Lock\n"); | 2420 | cifs_dbg(FYI, "Posix Lock\n"); |
2406 | 2421 | ||
@@ -2462,11 +2477,10 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
2462 | iov[0].iov_base = (char *)pSMB; | 2477 | iov[0].iov_base = (char *)pSMB; |
2463 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; | 2478 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
2464 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 2479 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
2465 | &resp_buf_type, timeout); | 2480 | &resp_buf_type, timeout, &rsp_iov); |
2466 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | 2481 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base; |
2467 | not try to free it twice below on exit */ | ||
2468 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; | ||
2469 | } | 2482 | } |
2483 | cifs_small_buf_release(pSMB); | ||
2470 | 2484 | ||
2471 | if (rc) { | 2485 | if (rc) { |
2472 | cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc); | 2486 | cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc); |
@@ -2506,10 +2520,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
2506 | } | 2520 | } |
2507 | 2521 | ||
2508 | plk_err_exit: | 2522 | plk_err_exit: |
2509 | if (pSMB) | 2523 | free_rsp_buf(resp_buf_type, rsp_iov.iov_base); |
2510 | cifs_small_buf_release(pSMB); | ||
2511 | |||
2512 | free_rsp_buf(resp_buf_type, iov[0].iov_base); | ||
2513 | 2524 | ||
2514 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 2525 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
2515 | since file handle passed in no longer valid */ | 2526 | since file handle passed in no longer valid */ |
@@ -2536,6 +2547,7 @@ CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2536 | pSMB->LastWriteTime = 0xFFFFFFFF; | 2547 | pSMB->LastWriteTime = 0xFFFFFFFF; |
2537 | pSMB->ByteCount = 0; | 2548 | pSMB->ByteCount = 0; |
2538 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 2549 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2550 | cifs_small_buf_release(pSMB); | ||
2539 | cifs_stats_inc(&tcon->stats.cifs_stats.num_closes); | 2551 | cifs_stats_inc(&tcon->stats.cifs_stats.num_closes); |
2540 | if (rc) { | 2552 | if (rc) { |
2541 | if (rc != -EINTR) { | 2553 | if (rc != -EINTR) { |
@@ -2565,6 +2577,7 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2565 | pSMB->FileID = (__u16) smb_file_id; | 2577 | pSMB->FileID = (__u16) smb_file_id; |
2566 | pSMB->ByteCount = 0; | 2578 | pSMB->ByteCount = 0; |
2567 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 2579 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2580 | cifs_small_buf_release(pSMB); | ||
2568 | cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes); | 2581 | cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes); |
2569 | if (rc) | 2582 | if (rc) |
2570 | cifs_dbg(VFS, "Send error in Flush = %d\n", rc); | 2583 | cifs_dbg(VFS, "Send error in Flush = %d\n", rc); |
@@ -3820,6 +3833,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, | |||
3820 | int buf_type = 0; | 3833 | int buf_type = 0; |
3821 | QUERY_SEC_DESC_REQ *pSMB; | 3834 | QUERY_SEC_DESC_REQ *pSMB; |
3822 | struct kvec iov[1]; | 3835 | struct kvec iov[1]; |
3836 | struct kvec rsp_iov; | ||
3823 | 3837 | ||
3824 | cifs_dbg(FYI, "GetCifsACL\n"); | 3838 | cifs_dbg(FYI, "GetCifsACL\n"); |
3825 | 3839 | ||
@@ -3843,7 +3857,8 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, | |||
3843 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; | 3857 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
3844 | 3858 | ||
3845 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3859 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3846 | 0); | 3860 | 0, &rsp_iov); |
3861 | cifs_small_buf_release(pSMB); | ||
3847 | cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get); | 3862 | cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get); |
3848 | if (rc) { | 3863 | if (rc) { |
3849 | cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc); | 3864 | cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc); |
@@ -3855,11 +3870,11 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, | |||
3855 | char *pdata; | 3870 | char *pdata; |
3856 | 3871 | ||
3857 | /* validate_nttransact */ | 3872 | /* validate_nttransact */ |
3858 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, | 3873 | rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm, |
3859 | &pdata, &parm_len, pbuflen); | 3874 | &pdata, &parm_len, pbuflen); |
3860 | if (rc) | 3875 | if (rc) |
3861 | goto qsec_out; | 3876 | goto qsec_out; |
3862 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; | 3877 | pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base; |
3863 | 3878 | ||
3864 | cifs_dbg(FYI, "smb %p parm %p data %p\n", | 3879 | cifs_dbg(FYI, "smb %p parm %p data %p\n", |
3865 | pSMBr, parm, *acl_inf); | 3880 | pSMBr, parm, *acl_inf); |
@@ -3896,8 +3911,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, | |||
3896 | } | 3911 | } |
3897 | } | 3912 | } |
3898 | qsec_out: | 3913 | qsec_out: |
3899 | free_rsp_buf(buf_type, iov[0].iov_base); | 3914 | free_rsp_buf(buf_type, rsp_iov.iov_base); |
3900 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | ||
3901 | return rc; | 3915 | return rc; |
3902 | } | 3916 | } |
3903 | 3917 | ||
@@ -4666,6 +4680,7 @@ CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon, | |||
4666 | pSMB->FileID = searchHandle; | 4680 | pSMB->FileID = searchHandle; |
4667 | pSMB->ByteCount = 0; | 4681 | pSMB->ByteCount = 0; |
4668 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 4682 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
4683 | cifs_small_buf_release(pSMB); | ||
4669 | if (rc) | 4684 | if (rc) |
4670 | cifs_dbg(VFS, "Send error in FindClose = %d\n", rc); | 4685 | cifs_dbg(VFS, "Send error in FindClose = %d\n", rc); |
4671 | 4686 | ||
@@ -5687,6 +5702,7 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, | |||
5687 | inc_rfc1001_len(pSMB, byte_count); | 5702 | inc_rfc1001_len(pSMB, byte_count); |
5688 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5703 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5689 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 5704 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5705 | cifs_small_buf_release(pSMB); | ||
5690 | if (rc) { | 5706 | if (rc) { |
5691 | cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n", | 5707 | cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n", |
5692 | rc); | 5708 | rc); |
@@ -5758,6 +5774,7 @@ CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, | |||
5758 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5774 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5759 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5775 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5760 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 5776 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5777 | cifs_small_buf_release(pSMB); | ||
5761 | if (rc) | 5778 | if (rc) |
5762 | cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n", | 5779 | cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n", |
5763 | rc); | 5780 | rc); |
@@ -5818,6 +5835,7 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon, | |||
5818 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5835 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5819 | *data_offset = delete_file ? 1 : 0; | 5836 | *data_offset = delete_file ? 1 : 0; |
5820 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 5837 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5838 | cifs_small_buf_release(pSMB); | ||
5821 | if (rc) | 5839 | if (rc) |
5822 | cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc); | 5840 | cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc); |
5823 | 5841 | ||
@@ -6057,6 +6075,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, | |||
6057 | cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args); | 6075 | cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args); |
6058 | 6076 | ||
6059 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); | 6077 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
6078 | cifs_small_buf_release(pSMB); | ||
6060 | if (rc) | 6079 | if (rc) |
6061 | cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n", | 6080 | cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n", |
6062 | rc); | 6081 | rc); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 35ae49ed1f76..777ad9f4fc3c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -787,6 +787,15 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
787 | 787 | ||
788 | dump_smb(buf, server->total_read); | 788 | dump_smb(buf, server->total_read); |
789 | 789 | ||
790 | return cifs_handle_standard(server, mid); | ||
791 | } | ||
792 | |||
793 | int | ||
794 | cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | ||
795 | { | ||
796 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; | ||
797 | int length; | ||
798 | |||
790 | /* | 799 | /* |
791 | * We know that we received enough to get to the MID as we | 800 | * We know that we received enough to get to the MID as we |
792 | * checked the pdu_length earlier. Now check to see | 801 | * checked the pdu_length earlier. Now check to see |
@@ -872,12 +881,19 @@ cifs_demultiplex_thread(void *p) | |||
872 | continue; | 881 | continue; |
873 | server->total_read += length; | 882 | server->total_read += length; |
874 | 883 | ||
875 | mid_entry = server->ops->find_mid(server, buf); | 884 | if (server->ops->is_transform_hdr && |
885 | server->ops->receive_transform && | ||
886 | server->ops->is_transform_hdr(buf)) { | ||
887 | length = server->ops->receive_transform(server, | ||
888 | &mid_entry); | ||
889 | } else { | ||
890 | mid_entry = server->ops->find_mid(server, buf); | ||
876 | 891 | ||
877 | if (!mid_entry || !mid_entry->receive) | 892 | if (!mid_entry || !mid_entry->receive) |
878 | length = standard_receive3(server, mid_entry); | 893 | length = standard_receive3(server, mid_entry); |
879 | else | 894 | else |
880 | length = mid_entry->receive(server, mid_entry); | 895 | length = mid_entry->receive(server, mid_entry); |
896 | } | ||
881 | 897 | ||
882 | if (length < 0) | 898 | if (length < 0) |
883 | continue; | 899 | continue; |
@@ -2154,7 +2170,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) | |||
2154 | server->tcpStatus = CifsExiting; | 2170 | server->tcpStatus = CifsExiting; |
2155 | spin_unlock(&GlobalMid_Lock); | 2171 | spin_unlock(&GlobalMid_Lock); |
2156 | 2172 | ||
2157 | cifs_crypto_shash_release(server); | 2173 | cifs_crypto_secmech_release(server); |
2158 | cifs_fscache_release_client_cookie(server); | 2174 | cifs_fscache_release_client_cookie(server); |
2159 | 2175 | ||
2160 | kfree(server->session_key.response); | 2176 | kfree(server->session_key.response); |
@@ -2273,7 +2289,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2273 | return tcp_ses; | 2289 | return tcp_ses; |
2274 | 2290 | ||
2275 | out_err_crypto_release: | 2291 | out_err_crypto_release: |
2276 | cifs_crypto_shash_release(tcp_ses); | 2292 | cifs_crypto_secmech_release(tcp_ses); |
2277 | 2293 | ||
2278 | put_net(cifs_net_ns(tcp_ses)); | 2294 | put_net(cifs_net_ns(tcp_ses)); |
2279 | 2295 | ||
@@ -2614,12 +2630,18 @@ get_ses_fail: | |||
2614 | return ERR_PTR(rc); | 2630 | return ERR_PTR(rc); |
2615 | } | 2631 | } |
2616 | 2632 | ||
2617 | static int match_tcon(struct cifs_tcon *tcon, const char *unc) | 2633 | static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) |
2618 | { | 2634 | { |
2619 | if (tcon->tidStatus == CifsExiting) | 2635 | if (tcon->tidStatus == CifsExiting) |
2620 | return 0; | 2636 | return 0; |
2621 | if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE)) | 2637 | if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE)) |
2622 | return 0; | 2638 | return 0; |
2639 | if (tcon->seal != volume_info->seal) | ||
2640 | return 0; | ||
2641 | #ifdef CONFIG_CIFS_SMB2 | ||
2642 | if (tcon->snapshot_time != volume_info->snapshot_time) | ||
2643 | return 0; | ||
2644 | #endif /* CONFIG_CIFS_SMB2 */ | ||
2623 | return 1; | 2645 | return 1; |
2624 | } | 2646 | } |
2625 | 2647 | ||
@@ -2632,14 +2654,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2632 | spin_lock(&cifs_tcp_ses_lock); | 2654 | spin_lock(&cifs_tcp_ses_lock); |
2633 | list_for_each(tmp, &ses->tcon_list) { | 2655 | list_for_each(tmp, &ses->tcon_list) { |
2634 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); | 2656 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); |
2635 | if (!match_tcon(tcon, volume_info->UNC)) | 2657 | if (!match_tcon(tcon, volume_info)) |
2636 | continue; | ||
2637 | |||
2638 | #ifdef CONFIG_CIFS_SMB2 | ||
2639 | if (tcon->snapshot_time != volume_info->snapshot_time) | ||
2640 | continue; | 2658 | continue; |
2641 | #endif /* CONFIG_CIFS_SMB2 */ | ||
2642 | |||
2643 | ++tcon->tc_count; | 2659 | ++tcon->tc_count; |
2644 | spin_unlock(&cifs_tcp_ses_lock); | 2660 | spin_unlock(&cifs_tcp_ses_lock); |
2645 | return tcon; | 2661 | return tcon; |
@@ -2685,8 +2701,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2685 | cifs_dbg(FYI, "Found match on UNC path\n"); | 2701 | cifs_dbg(FYI, "Found match on UNC path\n"); |
2686 | /* existing tcon already has a reference */ | 2702 | /* existing tcon already has a reference */ |
2687 | cifs_put_smb_ses(ses); | 2703 | cifs_put_smb_ses(ses); |
2688 | if (tcon->seal != volume_info->seal) | ||
2689 | cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n"); | ||
2690 | return tcon; | 2704 | return tcon; |
2691 | } | 2705 | } |
2692 | 2706 | ||
@@ -2742,7 +2756,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2742 | tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; | 2756 | tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; |
2743 | cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags); | 2757 | cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags); |
2744 | } | 2758 | } |
2745 | tcon->seal = volume_info->seal; | ||
2746 | tcon->use_persistent = false; | 2759 | tcon->use_persistent = false; |
2747 | /* check if SMB2 or later, CIFS does not support persistent handles */ | 2760 | /* check if SMB2 or later, CIFS does not support persistent handles */ |
2748 | if (volume_info->persistent) { | 2761 | if (volume_info->persistent) { |
@@ -2779,6 +2792,24 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2779 | tcon->use_resilient = true; | 2792 | tcon->use_resilient = true; |
2780 | } | 2793 | } |
2781 | 2794 | ||
2795 | if (volume_info->seal) { | ||
2796 | if (ses->server->vals->protocol_id == 0) { | ||
2797 | cifs_dbg(VFS, | ||
2798 | "SMB3 or later required for encryption\n"); | ||
2799 | rc = -EOPNOTSUPP; | ||
2800 | goto out_fail; | ||
2801 | #ifdef CONFIG_CIFS_SMB2 | ||
2802 | } else if (tcon->ses->server->capabilities & | ||
2803 | SMB2_GLOBAL_CAP_ENCRYPTION) | ||
2804 | tcon->seal = true; | ||
2805 | else { | ||
2806 | cifs_dbg(VFS, "Encryption is not supported on share\n"); | ||
2807 | rc = -EOPNOTSUPP; | ||
2808 | goto out_fail; | ||
2809 | #endif /* CONFIG_CIFS_SMB2 */ | ||
2810 | } | ||
2811 | } | ||
2812 | |||
2782 | /* | 2813 | /* |
2783 | * We can have only one retry value for a connection to a share so for | 2814 | * We can have only one retry value for a connection to a share so for |
2784 | * resources mounted more than once to the same server share the last | 2815 | * resources mounted more than once to the same server share the last |
@@ -2910,7 +2941,7 @@ cifs_match_super(struct super_block *sb, void *data) | |||
2910 | 2941 | ||
2911 | if (!match_server(tcp_srv, volume_info) || | 2942 | if (!match_server(tcp_srv, volume_info) || |
2912 | !match_session(ses, volume_info) || | 2943 | !match_session(ses, volume_info) || |
2913 | !match_tcon(tcon, volume_info->UNC) || | 2944 | !match_tcon(tcon, volume_info) || |
2914 | !match_prepath(sb, mnt_data)) { | 2945 | !match_prepath(sb, mnt_data)) { |
2915 | rc = 0; | 2946 | rc = 0; |
2916 | goto out; | 2947 | goto out; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 18a1e1d6671f..98dc842e7245 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2884,7 +2884,15 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) | |||
2884 | for (i = 0; i < rdata->nr_pages; i++) { | 2884 | for (i = 0; i < rdata->nr_pages; i++) { |
2885 | struct page *page = rdata->pages[i]; | 2885 | struct page *page = rdata->pages[i]; |
2886 | size_t copy = min_t(size_t, remaining, PAGE_SIZE); | 2886 | size_t copy = min_t(size_t, remaining, PAGE_SIZE); |
2887 | size_t written = copy_page_to_iter(page, 0, copy, iter); | 2887 | size_t written; |
2888 | |||
2889 | if (unlikely(iter->type & ITER_PIPE)) { | ||
2890 | void *addr = kmap_atomic(page); | ||
2891 | |||
2892 | written = copy_to_iter(addr, copy, iter); | ||
2893 | kunmap_atomic(addr); | ||
2894 | } else | ||
2895 | written = copy_page_to_iter(page, 0, copy, iter); | ||
2888 | remaining -= written; | 2896 | remaining -= written; |
2889 | if (written < copy && iov_iter_count(iter) > 0) | 2897 | if (written < copy && iov_iter_count(iter) > 0) |
2890 | break; | 2898 | break; |
@@ -2903,8 +2911,9 @@ cifs_uncached_readv_complete(struct work_struct *work) | |||
2903 | } | 2911 | } |
2904 | 2912 | ||
2905 | static int | 2913 | static int |
2906 | cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | 2914 | uncached_fill_pages(struct TCP_Server_Info *server, |
2907 | struct cifs_readdata *rdata, unsigned int len) | 2915 | struct cifs_readdata *rdata, struct iov_iter *iter, |
2916 | unsigned int len) | ||
2908 | { | 2917 | { |
2909 | int result = 0; | 2918 | int result = 0; |
2910 | unsigned int i; | 2919 | unsigned int i; |
@@ -2933,7 +2942,10 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | |||
2933 | rdata->tailsz = len; | 2942 | rdata->tailsz = len; |
2934 | len = 0; | 2943 | len = 0; |
2935 | } | 2944 | } |
2936 | result = cifs_read_page_from_socket(server, page, n); | 2945 | if (iter) |
2946 | result = copy_page_from_iter(page, 0, n, iter); | ||
2947 | else | ||
2948 | result = cifs_read_page_from_socket(server, page, n); | ||
2937 | if (result < 0) | 2949 | if (result < 0) |
2938 | break; | 2950 | break; |
2939 | 2951 | ||
@@ -2945,6 +2957,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | |||
2945 | } | 2957 | } |
2946 | 2958 | ||
2947 | static int | 2959 | static int |
2960 | cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | ||
2961 | struct cifs_readdata *rdata, unsigned int len) | ||
2962 | { | ||
2963 | return uncached_fill_pages(server, rdata, NULL, len); | ||
2964 | } | ||
2965 | |||
2966 | static int | ||
2967 | cifs_uncached_copy_into_pages(struct TCP_Server_Info *server, | ||
2968 | struct cifs_readdata *rdata, | ||
2969 | struct iov_iter *iter) | ||
2970 | { | ||
2971 | return uncached_fill_pages(server, rdata, iter, iter->count); | ||
2972 | } | ||
2973 | |||
2974 | static int | ||
2948 | cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | 2975 | cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, |
2949 | struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) | 2976 | struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) |
2950 | { | 2977 | { |
@@ -2991,6 +3018,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
2991 | rdata->pid = pid; | 3018 | rdata->pid = pid; |
2992 | rdata->pagesz = PAGE_SIZE; | 3019 | rdata->pagesz = PAGE_SIZE; |
2993 | rdata->read_into_pages = cifs_uncached_read_into_pages; | 3020 | rdata->read_into_pages = cifs_uncached_read_into_pages; |
3021 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; | ||
2994 | rdata->credits = credits; | 3022 | rdata->credits = credits; |
2995 | 3023 | ||
2996 | if (!rdata->cfile->invalidHandle || | 3024 | if (!rdata->cfile->invalidHandle || |
@@ -3341,8 +3369,9 @@ cifs_readv_complete(struct work_struct *work) | |||
3341 | } | 3369 | } |
3342 | 3370 | ||
3343 | static int | 3371 | static int |
3344 | cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | 3372 | readpages_fill_pages(struct TCP_Server_Info *server, |
3345 | struct cifs_readdata *rdata, unsigned int len) | 3373 | struct cifs_readdata *rdata, struct iov_iter *iter, |
3374 | unsigned int len) | ||
3346 | { | 3375 | { |
3347 | int result = 0; | 3376 | int result = 0; |
3348 | unsigned int i; | 3377 | unsigned int i; |
@@ -3396,7 +3425,10 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | |||
3396 | continue; | 3425 | continue; |
3397 | } | 3426 | } |
3398 | 3427 | ||
3399 | result = cifs_read_page_from_socket(server, page, n); | 3428 | if (iter) |
3429 | result = copy_page_from_iter(page, 0, n, iter); | ||
3430 | else | ||
3431 | result = cifs_read_page_from_socket(server, page, n); | ||
3400 | if (result < 0) | 3432 | if (result < 0) |
3401 | break; | 3433 | break; |
3402 | 3434 | ||
@@ -3408,6 +3440,21 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | |||
3408 | } | 3440 | } |
3409 | 3441 | ||
3410 | static int | 3442 | static int |
3443 | cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | ||
3444 | struct cifs_readdata *rdata, unsigned int len) | ||
3445 | { | ||
3446 | return readpages_fill_pages(server, rdata, NULL, len); | ||
3447 | } | ||
3448 | |||
3449 | static int | ||
3450 | cifs_readpages_copy_into_pages(struct TCP_Server_Info *server, | ||
3451 | struct cifs_readdata *rdata, | ||
3452 | struct iov_iter *iter) | ||
3453 | { | ||
3454 | return readpages_fill_pages(server, rdata, iter, iter->count); | ||
3455 | } | ||
3456 | |||
3457 | static int | ||
3411 | readpages_get_pages(struct address_space *mapping, struct list_head *page_list, | 3458 | readpages_get_pages(struct address_space *mapping, struct list_head *page_list, |
3412 | unsigned int rsize, struct list_head *tmplist, | 3459 | unsigned int rsize, struct list_head *tmplist, |
3413 | unsigned int *nr_pages, loff_t *offset, unsigned int *bytes) | 3460 | unsigned int *nr_pages, loff_t *offset, unsigned int *bytes) |
@@ -3561,6 +3608,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3561 | rdata->pid = pid; | 3608 | rdata->pid = pid; |
3562 | rdata->pagesz = PAGE_SIZE; | 3609 | rdata->pagesz = PAGE_SIZE; |
3563 | rdata->read_into_pages = cifs_readpages_read_into_pages; | 3610 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
3611 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; | ||
3564 | rdata->credits = credits; | 3612 | rdata->credits = credits; |
3565 | 3613 | ||
3566 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { | 3614 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 538d9b55699a..dcbcc927399a 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -344,13 +344,12 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
344 | /* BB is NTLMV2 session security format easier to use here? */ | 344 | /* BB is NTLMV2 session security format easier to use here? */ |
345 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 345 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
346 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 346 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
347 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 347 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | |
348 | if (ses->server->sign) { | 348 | NTLMSSP_NEGOTIATE_SEAL; |
349 | if (ses->server->sign) | ||
349 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 350 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
350 | if (!ses->server->session_estab || | 351 | if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) |
351 | ses->ntlmssp->sesskey_per_smbsess) | 352 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
352 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | ||
353 | } | ||
354 | 353 | ||
355 | sec_blob->NegotiateFlags = cpu_to_le32(flags); | 354 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
356 | 355 | ||
@@ -407,13 +406,12 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, | |||
407 | flags = NTLMSSP_NEGOTIATE_56 | | 406 | flags = NTLMSSP_NEGOTIATE_56 | |
408 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | | 407 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | |
409 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 408 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
410 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 409 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | |
411 | if (ses->server->sign) { | 410 | NTLMSSP_NEGOTIATE_SEAL; |
411 | if (ses->server->sign) | ||
412 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 412 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
413 | if (!ses->server->session_estab || | 413 | if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) |
414 | ses->ntlmssp->sesskey_per_smbsess) | 414 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
415 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | ||
416 | } | ||
417 | 415 | ||
418 | tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); | 416 | tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); |
419 | sec_blob->NegotiateFlags = cpu_to_le32(flags); | 417 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
@@ -652,6 +650,7 @@ sess_sendreceive(struct sess_data *sess_data) | |||
652 | int rc; | 650 | int rc; |
653 | struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base; | 651 | struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base; |
654 | __u16 count; | 652 | __u16 count; |
653 | struct kvec rsp_iov = { NULL, 0 }; | ||
655 | 654 | ||
656 | count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len; | 655 | count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len; |
657 | smb_buf->smb_buf_length = | 656 | smb_buf->smb_buf_length = |
@@ -661,7 +660,9 @@ sess_sendreceive(struct sess_data *sess_data) | |||
661 | rc = SendReceive2(sess_data->xid, sess_data->ses, | 660 | rc = SendReceive2(sess_data->xid, sess_data->ses, |
662 | sess_data->iov, 3 /* num_iovecs */, | 661 | sess_data->iov, 3 /* num_iovecs */, |
663 | &sess_data->buf0_type, | 662 | &sess_data->buf0_type, |
664 | CIFS_LOG_ERROR); | 663 | CIFS_LOG_ERROR, &rsp_iov); |
664 | cifs_small_buf_release(sess_data->iov[0].iov_base); | ||
665 | memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec)); | ||
665 | 666 | ||
666 | return rc; | 667 | return rc; |
667 | } | 668 | } |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index fc537c29044e..67a987e4d026 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -36,11 +36,11 @@ | |||
36 | * SMB_COM_NT_CANCEL request and then sends it. | 36 | * SMB_COM_NT_CANCEL request and then sends it. |
37 | */ | 37 | */ |
38 | static int | 38 | static int |
39 | send_nt_cancel(struct TCP_Server_Info *server, void *buf, | 39 | send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, |
40 | struct mid_q_entry *mid) | 40 | struct mid_q_entry *mid) |
41 | { | 41 | { |
42 | int rc = 0; | 42 | int rc = 0; |
43 | struct smb_hdr *in_buf = (struct smb_hdr *)buf; | 43 | struct smb_hdr *in_buf = (struct smb_hdr *)rqst->rq_iov[0].iov_base; |
44 | 44 | ||
45 | /* -4 for RFC1001 length and +2 for BCC field */ | 45 | /* -4 for RFC1001 length and +2 for BCC field */ |
46 | in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); | 46 | in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); |
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index 0ffa18094335..401a5d856636 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h | |||
@@ -61,4 +61,9 @@ | |||
61 | /* Maximum buffer size value we can send with 1 credit */ | 61 | /* Maximum buffer size value we can send with 1 credit */ |
62 | #define SMB2_MAX_BUFFER_SIZE 65536 | 62 | #define SMB2_MAX_BUFFER_SIZE 65536 |
63 | 63 | ||
64 | static inline struct smb2_sync_hdr *get_sync_hdr(void *buf) | ||
65 | { | ||
66 | return &(((struct smb2_hdr *)buf)->sync_hdr); | ||
67 | } | ||
68 | |||
64 | #endif /* _SMB2_GLOB_H */ | 69 | #endif /* _SMB2_GLOB_H */ |
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index 8257a5a97cc0..3030a9dfb0dd 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "smb2pdu.h" | 26 | #include "smb2pdu.h" |
27 | #include "smb2proto.h" | 27 | #include "smb2proto.h" |
28 | #include "smb2status.h" | 28 | #include "smb2status.h" |
29 | #include "smb2glob.h" | ||
29 | 30 | ||
30 | struct status_to_posix_error { | 31 | struct status_to_posix_error { |
31 | __le32 smb2_status; | 32 | __le32 smb2_status; |
@@ -2449,10 +2450,10 @@ smb2_print_status(__le32 status) | |||
2449 | int | 2450 | int |
2450 | map_smb2_to_linux_error(char *buf, bool log_err) | 2451 | map_smb2_to_linux_error(char *buf, bool log_err) |
2451 | { | 2452 | { |
2452 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 2453 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); |
2453 | unsigned int i; | 2454 | unsigned int i; |
2454 | int rc = -EIO; | 2455 | int rc = -EIO; |
2455 | __le32 smb2err = hdr->Status; | 2456 | __le32 smb2err = shdr->Status; |
2456 | 2457 | ||
2457 | if (smb2err == 0) | 2458 | if (smb2err == 0) |
2458 | return 0; | 2459 | return 0; |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 3d383489b9cf..fd516ea8b8f8 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -28,31 +28,32 @@ | |||
28 | #include "cifs_debug.h" | 28 | #include "cifs_debug.h" |
29 | #include "cifs_unicode.h" | 29 | #include "cifs_unicode.h" |
30 | #include "smb2status.h" | 30 | #include "smb2status.h" |
31 | #include "smb2glob.h" | ||
31 | 32 | ||
32 | static int | 33 | static int |
33 | check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | 34 | check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid) |
34 | { | 35 | { |
35 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | 36 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
36 | 37 | ||
37 | /* | 38 | /* |
38 | * Make sure that this really is an SMB, that it is a response, | 39 | * Make sure that this really is an SMB, that it is a response, |
39 | * and that the message ids match. | 40 | * and that the message ids match. |
40 | */ | 41 | */ |
41 | if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) && | 42 | if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) && |
42 | (mid == wire_mid)) { | 43 | (mid == wire_mid)) { |
43 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) | 44 | if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
44 | return 0; | 45 | return 0; |
45 | else { | 46 | else { |
46 | /* only one valid case where server sends us request */ | 47 | /* only one valid case where server sends us request */ |
47 | if (hdr->Command == SMB2_OPLOCK_BREAK) | 48 | if (shdr->Command == SMB2_OPLOCK_BREAK) |
48 | return 0; | 49 | return 0; |
49 | else | 50 | else |
50 | cifs_dbg(VFS, "Received Request not response\n"); | 51 | cifs_dbg(VFS, "Received Request not response\n"); |
51 | } | 52 | } |
52 | } else { /* bad signature or mid */ | 53 | } else { /* bad signature or mid */ |
53 | if (hdr->ProtocolId != SMB2_PROTO_NUMBER) | 54 | if (shdr->ProtocolId != SMB2_PROTO_NUMBER) |
54 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", | 55 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", |
55 | le32_to_cpu(hdr->ProtocolId)); | 56 | le32_to_cpu(shdr->ProtocolId)); |
56 | if (mid != wire_mid) | 57 | if (mid != wire_mid) |
57 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", | 58 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", |
58 | mid, wire_mid); | 59 | mid, wire_mid); |
@@ -95,8 +96,9 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
95 | int | 96 | int |
96 | smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | 97 | smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) |
97 | { | 98 | { |
98 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 99 | struct smb2_pdu *pdu = (struct smb2_pdu *)buf; |
99 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 100 | struct smb2_hdr *hdr = &pdu->hdr; |
101 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | ||
100 | __u64 mid; | 102 | __u64 mid; |
101 | __u32 len = get_rfc1002_length(buf); | 103 | __u32 len = get_rfc1002_length(buf); |
102 | __u32 clc_len; /* calculated length */ | 104 | __u32 clc_len; /* calculated length */ |
@@ -111,7 +113,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
111 | * ie Validate the wct via smb2_struct_sizes table above | 113 | * ie Validate the wct via smb2_struct_sizes table above |
112 | */ | 114 | */ |
113 | 115 | ||
114 | if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 116 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
115 | struct smb2_transform_hdr *thdr = | 117 | struct smb2_transform_hdr *thdr = |
116 | (struct smb2_transform_hdr *)buf; | 118 | (struct smb2_transform_hdr *)buf; |
117 | struct cifs_ses *ses = NULL; | 119 | struct cifs_ses *ses = NULL; |
@@ -133,10 +135,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
133 | } | 135 | } |
134 | } | 136 | } |
135 | 137 | ||
136 | 138 | mid = le64_to_cpu(shdr->MessageId); | |
137 | mid = le64_to_cpu(hdr->MessageId); | ||
138 | if (length < sizeof(struct smb2_pdu)) { | 139 | if (length < sizeof(struct smb2_pdu)) { |
139 | if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { | 140 | if ((length >= sizeof(struct smb2_hdr)) |
141 | && (shdr->Status != 0)) { | ||
140 | pdu->StructureSize2 = 0; | 142 | pdu->StructureSize2 = 0; |
141 | /* | 143 | /* |
142 | * As with SMB/CIFS, on some error cases servers may | 144 | * As with SMB/CIFS, on some error cases servers may |
@@ -154,29 +156,30 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
154 | return 1; | 156 | return 1; |
155 | } | 157 | } |
156 | 158 | ||
157 | if (check_smb2_hdr(hdr, mid)) | 159 | if (check_smb2_hdr(shdr, mid)) |
158 | return 1; | 160 | return 1; |
159 | 161 | ||
160 | if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { | 162 | if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { |
161 | cifs_dbg(VFS, "Illegal structure size %u\n", | 163 | cifs_dbg(VFS, "Illegal structure size %u\n", |
162 | le16_to_cpu(hdr->StructureSize)); | 164 | le16_to_cpu(shdr->StructureSize)); |
163 | return 1; | 165 | return 1; |
164 | } | 166 | } |
165 | 167 | ||
166 | command = le16_to_cpu(hdr->Command); | 168 | command = le16_to_cpu(shdr->Command); |
167 | if (command >= NUMBER_OF_SMB2_COMMANDS) { | 169 | if (command >= NUMBER_OF_SMB2_COMMANDS) { |
168 | cifs_dbg(VFS, "Illegal SMB2 command %d\n", command); | 170 | cifs_dbg(VFS, "Illegal SMB2 command %d\n", command); |
169 | return 1; | 171 | return 1; |
170 | } | 172 | } |
171 | 173 | ||
172 | if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) { | 174 | if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) { |
173 | if (command != SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0 || | 175 | if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 || |
174 | pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { | 176 | pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { |
175 | /* error packets have 9 byte structure size */ | 177 | /* error packets have 9 byte structure size */ |
176 | cifs_dbg(VFS, "Illegal response size %u for command %d\n", | 178 | cifs_dbg(VFS, "Illegal response size %u for command %d\n", |
177 | le16_to_cpu(pdu->StructureSize2), command); | 179 | le16_to_cpu(pdu->StructureSize2), command); |
178 | return 1; | 180 | return 1; |
179 | } else if (command == SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0) | 181 | } else if (command == SMB2_OPLOCK_BREAK_HE |
182 | && (shdr->Status == 0) | ||
180 | && (le16_to_cpu(pdu->StructureSize2) != 44) | 183 | && (le16_to_cpu(pdu->StructureSize2) != 44) |
181 | && (le16_to_cpu(pdu->StructureSize2) != 36)) { | 184 | && (le16_to_cpu(pdu->StructureSize2) != 36)) { |
182 | /* special case for SMB2.1 lease break message */ | 185 | /* special case for SMB2.1 lease break message */ |
@@ -199,7 +202,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
199 | clc_len, 4 + len, mid); | 202 | clc_len, 4 + len, mid); |
200 | /* create failed on symlink */ | 203 | /* create failed on symlink */ |
201 | if (command == SMB2_CREATE_HE && | 204 | if (command == SMB2_CREATE_HE && |
202 | hdr->Status == STATUS_STOPPED_ON_SYMLINK) | 205 | shdr->Status == STATUS_STOPPED_ON_SYMLINK) |
203 | return 0; | 206 | return 0; |
204 | /* Windows 7 server returns 24 bytes more */ | 207 | /* Windows 7 server returns 24 bytes more */ |
205 | if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) | 208 | if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) |
@@ -261,11 +264,12 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { | |||
261 | char * | 264 | char * |
262 | smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | 265 | smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) |
263 | { | 266 | { |
267 | struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); | ||
264 | *off = 0; | 268 | *off = 0; |
265 | *len = 0; | 269 | *len = 0; |
266 | 270 | ||
267 | /* error responses do not have data area */ | 271 | /* error responses do not have data area */ |
268 | if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED && | 272 | if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && |
269 | (((struct smb2_err_rsp *)hdr)->StructureSize) == | 273 | (((struct smb2_err_rsp *)hdr)->StructureSize) == |
270 | SMB2_ERROR_STRUCTURE_SIZE2) | 274 | SMB2_ERROR_STRUCTURE_SIZE2) |
271 | return NULL; | 275 | return NULL; |
@@ -275,7 +279,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
275 | * of the data buffer offset and data buffer length for the particular | 279 | * of the data buffer offset and data buffer length for the particular |
276 | * command. | 280 | * command. |
277 | */ | 281 | */ |
278 | switch (hdr->Command) { | 282 | switch (shdr->Command) { |
279 | case SMB2_NEGOTIATE: | 283 | case SMB2_NEGOTIATE: |
280 | *off = le16_to_cpu( | 284 | *off = le16_to_cpu( |
281 | ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); | 285 | ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); |
@@ -346,7 +350,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
346 | 350 | ||
347 | /* return pointer to beginning of data area, ie offset from SMB start */ | 351 | /* return pointer to beginning of data area, ie offset from SMB start */ |
348 | if ((*off != 0) && (*len != 0)) | 352 | if ((*off != 0) && (*len != 0)) |
349 | return (char *)(&hdr->ProtocolId) + *off; | 353 | return (char *)shdr + *off; |
350 | else | 354 | else |
351 | return NULL; | 355 | return NULL; |
352 | } | 356 | } |
@@ -358,12 +362,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
358 | unsigned int | 362 | unsigned int |
359 | smb2_calc_size(void *buf) | 363 | smb2_calc_size(void *buf) |
360 | { | 364 | { |
361 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 365 | struct smb2_pdu *pdu = (struct smb2_pdu *)buf; |
362 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 366 | struct smb2_hdr *hdr = &pdu->hdr; |
367 | struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); | ||
363 | int offset; /* the offset from the beginning of SMB to data area */ | 368 | int offset; /* the offset from the beginning of SMB to data area */ |
364 | int data_length; /* the length of the variable length data area */ | 369 | int data_length; /* the length of the variable length data area */ |
365 | /* Structure Size has already been checked to make sure it is 64 */ | 370 | /* Structure Size has already been checked to make sure it is 64 */ |
366 | int len = 4 + le16_to_cpu(pdu->hdr.StructureSize); | 371 | int len = 4 + le16_to_cpu(shdr->StructureSize); |
367 | 372 | ||
368 | /* | 373 | /* |
369 | * StructureSize2, ie length of fixed parameter area has already | 374 | * StructureSize2, ie length of fixed parameter area has already |
@@ -371,7 +376,7 @@ smb2_calc_size(void *buf) | |||
371 | */ | 376 | */ |
372 | len += le16_to_cpu(pdu->StructureSize2); | 377 | len += le16_to_cpu(pdu->StructureSize2); |
373 | 378 | ||
374 | if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false) | 379 | if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) |
375 | goto calc_size_exit; | 380 | goto calc_size_exit; |
376 | 381 | ||
377 | smb2_get_data_area_len(&offset, &data_length, hdr); | 382 | smb2_get_data_area_len(&offset, &data_length, hdr); |
@@ -582,7 +587,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) | |||
582 | 587 | ||
583 | cifs_dbg(FYI, "Checking for oplock break\n"); | 588 | cifs_dbg(FYI, "Checking for oplock break\n"); |
584 | 589 | ||
585 | if (rsp->hdr.Command != SMB2_OPLOCK_BREAK) | 590 | if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK) |
586 | return false; | 591 | return false; |
587 | 592 | ||
588 | if (rsp->StructureSize != | 593 | if (rsp->StructureSize != |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 5d456ebb3813..a44b4dbe4aae 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
21 | #include <linux/vfs.h> | 21 | #include <linux/vfs.h> |
22 | #include <linux/falloc.h> | 22 | #include <linux/falloc.h> |
23 | #include <linux/scatterlist.h> | ||
24 | #include <crypto/aead.h> | ||
23 | #include "cifsglob.h" | 25 | #include "cifsglob.h" |
24 | #include "smb2pdu.h" | 26 | #include "smb2pdu.h" |
25 | #include "smb2proto.h" | 27 | #include "smb2proto.h" |
@@ -119,7 +121,9 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) | |||
119 | static unsigned int | 121 | static unsigned int |
120 | smb2_get_credits(struct mid_q_entry *mid) | 122 | smb2_get_credits(struct mid_q_entry *mid) |
121 | { | 123 | { |
122 | return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest); | 124 | struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf); |
125 | |||
126 | return le16_to_cpu(shdr->CreditRequest); | ||
123 | } | 127 | } |
124 | 128 | ||
125 | static int | 129 | static int |
@@ -184,10 +188,10 @@ static struct mid_q_entry * | |||
184 | smb2_find_mid(struct TCP_Server_Info *server, char *buf) | 188 | smb2_find_mid(struct TCP_Server_Info *server, char *buf) |
185 | { | 189 | { |
186 | struct mid_q_entry *mid; | 190 | struct mid_q_entry *mid; |
187 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 191 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); |
188 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | 192 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
189 | 193 | ||
190 | if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 194 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
191 | cifs_dbg(VFS, "encrypted frame parsing not supported yet"); | 195 | cifs_dbg(VFS, "encrypted frame parsing not supported yet"); |
192 | return NULL; | 196 | return NULL; |
193 | } | 197 | } |
@@ -196,7 +200,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
196 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { | 200 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
197 | if ((mid->mid == wire_mid) && | 201 | if ((mid->mid == wire_mid) && |
198 | (mid->mid_state == MID_REQUEST_SUBMITTED) && | 202 | (mid->mid_state == MID_REQUEST_SUBMITTED) && |
199 | (mid->command == hdr->Command)) { | 203 | (mid->command == shdr->Command)) { |
200 | spin_unlock(&GlobalMid_Lock); | 204 | spin_unlock(&GlobalMid_Lock); |
201 | return mid; | 205 | return mid; |
202 | } | 206 | } |
@@ -209,12 +213,12 @@ static void | |||
209 | smb2_dump_detail(void *buf) | 213 | smb2_dump_detail(void *buf) |
210 | { | 214 | { |
211 | #ifdef CONFIG_CIFS_DEBUG2 | 215 | #ifdef CONFIG_CIFS_DEBUG2 |
212 | struct smb2_hdr *smb = (struct smb2_hdr *)buf; | 216 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); |
213 | 217 | ||
214 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", | 218 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", |
215 | smb->Command, smb->Status, smb->Flags, smb->MessageId, | 219 | shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, |
216 | smb->ProcessId); | 220 | shdr->ProcessId); |
217 | cifs_dbg(VFS, "smb buf %p len %u\n", smb, smb2_calc_size(smb)); | 221 | cifs_dbg(VFS, "smb buf %p len %u\n", buf, smb2_calc_size(buf)); |
218 | #endif | 222 | #endif |
219 | } | 223 | } |
220 | 224 | ||
@@ -1002,14 +1006,14 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, | |||
1002 | static bool | 1006 | static bool |
1003 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) | 1007 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) |
1004 | { | 1008 | { |
1005 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 1009 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); |
1006 | 1010 | ||
1007 | if (hdr->Status != STATUS_PENDING) | 1011 | if (shdr->Status != STATUS_PENDING) |
1008 | return false; | 1012 | return false; |
1009 | 1013 | ||
1010 | if (!length) { | 1014 | if (!length) { |
1011 | spin_lock(&server->req_lock); | 1015 | spin_lock(&server->req_lock); |
1012 | server->credits += le16_to_cpu(hdr->CreditRequest); | 1016 | server->credits += le16_to_cpu(shdr->CreditRequest); |
1013 | spin_unlock(&server->req_lock); | 1017 | spin_unlock(&server->req_lock); |
1014 | wake_up(&server->request_q); | 1018 | wake_up(&server->request_q); |
1015 | } | 1019 | } |
@@ -1545,6 +1549,633 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile) | |||
1545 | return !cfile->invalidHandle; | 1549 | return !cfile->invalidHandle; |
1546 | } | 1550 | } |
1547 | 1551 | ||
1552 | static void | ||
1553 | fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq) | ||
1554 | { | ||
1555 | struct smb2_sync_hdr *shdr = | ||
1556 | (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base; | ||
1557 | unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); | ||
1558 | |||
1559 | memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); | ||
1560 | tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; | ||
1561 | tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len); | ||
1562 | tr_hdr->Flags = cpu_to_le16(0x01); | ||
1563 | get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE); | ||
1564 | memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); | ||
1565 | inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4); | ||
1566 | inc_rfc1001_len(tr_hdr, orig_len); | ||
1567 | } | ||
1568 | |||
1569 | static struct scatterlist * | ||
1570 | init_sg(struct smb_rqst *rqst, u8 *sign) | ||
1571 | { | ||
1572 | unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1; | ||
1573 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; | ||
1574 | struct scatterlist *sg; | ||
1575 | unsigned int i; | ||
1576 | unsigned int j; | ||
1577 | |||
1578 | sg = kmalloc_array(sg_len, sizeof(struct scatterlist), GFP_KERNEL); | ||
1579 | if (!sg) | ||
1580 | return NULL; | ||
1581 | |||
1582 | sg_init_table(sg, sg_len); | ||
1583 | sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len); | ||
1584 | for (i = 1; i < rqst->rq_nvec; i++) | ||
1585 | sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base, | ||
1586 | rqst->rq_iov[i].iov_len); | ||
1587 | for (j = 0; i < sg_len - 1; i++, j++) { | ||
1588 | unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz | ||
1589 | : rqst->rq_tailsz; | ||
1590 | sg_set_page(&sg[i], rqst->rq_pages[j], len, 0); | ||
1591 | } | ||
1592 | sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE); | ||
1593 | return sg; | ||
1594 | } | ||
1595 | |||
1596 | struct cifs_crypt_result { | ||
1597 | int err; | ||
1598 | struct completion completion; | ||
1599 | }; | ||
1600 | |||
1601 | static void cifs_crypt_complete(struct crypto_async_request *req, int err) | ||
1602 | { | ||
1603 | struct cifs_crypt_result *res = req->data; | ||
1604 | |||
1605 | if (err == -EINPROGRESS) | ||
1606 | return; | ||
1607 | |||
1608 | res->err = err; | ||
1609 | complete(&res->completion); | ||
1610 | } | ||
1611 | |||
1612 | /* | ||
1613 | * Encrypt or decrypt @rqst message. @rqst has the following format: | ||
1614 | * iov[0] - transform header (associate data), | ||
1615 | * iov[1-N] and pages - data to encrypt. | ||
1616 | * On success return encrypted data in iov[1-N] and pages, leave iov[0] | ||
1617 | * untouched. | ||
1618 | */ | ||
1619 | static int | ||
1620 | crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) | ||
1621 | { | ||
1622 | struct smb2_transform_hdr *tr_hdr = | ||
1623 | (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base; | ||
1624 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; | ||
1625 | struct cifs_ses *ses; | ||
1626 | int rc = 0; | ||
1627 | struct scatterlist *sg; | ||
1628 | u8 sign[SMB2_SIGNATURE_SIZE] = {}; | ||
1629 | struct aead_request *req; | ||
1630 | char *iv; | ||
1631 | unsigned int iv_len; | ||
1632 | struct cifs_crypt_result result = {0, }; | ||
1633 | struct crypto_aead *tfm; | ||
1634 | unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); | ||
1635 | |||
1636 | init_completion(&result.completion); | ||
1637 | |||
1638 | ses = smb2_find_smb_ses(server, tr_hdr->SessionId); | ||
1639 | if (!ses) { | ||
1640 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | ||
1641 | return 0; | ||
1642 | } | ||
1643 | |||
1644 | rc = smb3_crypto_aead_allocate(server); | ||
1645 | if (rc) { | ||
1646 | cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); | ||
1647 | return rc; | ||
1648 | } | ||
1649 | |||
1650 | tfm = enc ? server->secmech.ccmaesencrypt : | ||
1651 | server->secmech.ccmaesdecrypt; | ||
1652 | rc = crypto_aead_setkey(tfm, enc ? ses->smb3encryptionkey : | ||
1653 | ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE); | ||
1654 | if (rc) { | ||
1655 | cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); | ||
1656 | return rc; | ||
1657 | } | ||
1658 | |||
1659 | rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); | ||
1660 | if (rc) { | ||
1661 | cifs_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); | ||
1662 | return rc; | ||
1663 | } | ||
1664 | |||
1665 | req = aead_request_alloc(tfm, GFP_KERNEL); | ||
1666 | if (!req) { | ||
1667 | cifs_dbg(VFS, "%s: Failed to alloc aead request", __func__); | ||
1668 | return -ENOMEM; | ||
1669 | } | ||
1670 | |||
1671 | if (!enc) { | ||
1672 | memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE); | ||
1673 | crypt_len += SMB2_SIGNATURE_SIZE; | ||
1674 | } | ||
1675 | |||
1676 | sg = init_sg(rqst, sign); | ||
1677 | if (!sg) { | ||
1678 | cifs_dbg(VFS, "%s: Failed to init sg %d", __func__, rc); | ||
1679 | goto free_req; | ||
1680 | } | ||
1681 | |||
1682 | iv_len = crypto_aead_ivsize(tfm); | ||
1683 | iv = kzalloc(iv_len, GFP_KERNEL); | ||
1684 | if (!iv) { | ||
1685 | cifs_dbg(VFS, "%s: Failed to alloc IV", __func__); | ||
1686 | goto free_sg; | ||
1687 | } | ||
1688 | iv[0] = 3; | ||
1689 | memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES128CMM_NONCE); | ||
1690 | |||
1691 | aead_request_set_crypt(req, sg, sg, crypt_len, iv); | ||
1692 | aead_request_set_ad(req, assoc_data_len); | ||
1693 | |||
1694 | aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | ||
1695 | cifs_crypt_complete, &result); | ||
1696 | |||
1697 | rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); | ||
1698 | |||
1699 | if (rc == -EINPROGRESS || rc == -EBUSY) { | ||
1700 | wait_for_completion(&result.completion); | ||
1701 | rc = result.err; | ||
1702 | } | ||
1703 | |||
1704 | if (!rc && enc) | ||
1705 | memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); | ||
1706 | |||
1707 | kfree(iv); | ||
1708 | free_sg: | ||
1709 | kfree(sg); | ||
1710 | free_req: | ||
1711 | kfree(req); | ||
1712 | return rc; | ||
1713 | } | ||
1714 | |||
1715 | static int | ||
1716 | smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, | ||
1717 | struct smb_rqst *old_rq) | ||
1718 | { | ||
1719 | struct kvec *iov; | ||
1720 | struct page **pages; | ||
1721 | struct smb2_transform_hdr *tr_hdr; | ||
1722 | unsigned int npages = old_rq->rq_npages; | ||
1723 | int i; | ||
1724 | int rc = -ENOMEM; | ||
1725 | |||
1726 | pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); | ||
1727 | if (!pages) | ||
1728 | return rc; | ||
1729 | |||
1730 | new_rq->rq_pages = pages; | ||
1731 | new_rq->rq_npages = old_rq->rq_npages; | ||
1732 | new_rq->rq_pagesz = old_rq->rq_pagesz; | ||
1733 | new_rq->rq_tailsz = old_rq->rq_tailsz; | ||
1734 | |||
1735 | for (i = 0; i < npages; i++) { | ||
1736 | pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); | ||
1737 | if (!pages[i]) | ||
1738 | goto err_free_pages; | ||
1739 | } | ||
1740 | |||
1741 | iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL); | ||
1742 | if (!iov) | ||
1743 | goto err_free_pages; | ||
1744 | |||
1745 | /* copy all iovs from the old except the 1st one (rfc1002 length) */ | ||
1746 | memcpy(&iov[1], &old_rq->rq_iov[1], | ||
1747 | sizeof(struct kvec) * (old_rq->rq_nvec - 1)); | ||
1748 | new_rq->rq_iov = iov; | ||
1749 | new_rq->rq_nvec = old_rq->rq_nvec; | ||
1750 | |||
1751 | tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL); | ||
1752 | if (!tr_hdr) | ||
1753 | goto err_free_iov; | ||
1754 | |||
1755 | /* fill the 1st iov with a transform header */ | ||
1756 | fill_transform_hdr(tr_hdr, old_rq); | ||
1757 | new_rq->rq_iov[0].iov_base = tr_hdr; | ||
1758 | new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr); | ||
1759 | |||
1760 | /* copy pages form the old */ | ||
1761 | for (i = 0; i < npages; i++) { | ||
1762 | char *dst = kmap(new_rq->rq_pages[i]); | ||
1763 | char *src = kmap(old_rq->rq_pages[i]); | ||
1764 | unsigned int len = (i < npages - 1) ? new_rq->rq_pagesz : | ||
1765 | new_rq->rq_tailsz; | ||
1766 | memcpy(dst, src, len); | ||
1767 | kunmap(new_rq->rq_pages[i]); | ||
1768 | kunmap(old_rq->rq_pages[i]); | ||
1769 | } | ||
1770 | |||
1771 | rc = crypt_message(server, new_rq, 1); | ||
1772 | cifs_dbg(FYI, "encrypt message returned %d", rc); | ||
1773 | if (rc) | ||
1774 | goto err_free_tr_hdr; | ||
1775 | |||
1776 | return rc; | ||
1777 | |||
1778 | err_free_tr_hdr: | ||
1779 | kfree(tr_hdr); | ||
1780 | err_free_iov: | ||
1781 | kfree(iov); | ||
1782 | err_free_pages: | ||
1783 | for (i = i - 1; i >= 0; i--) | ||
1784 | put_page(pages[i]); | ||
1785 | kfree(pages); | ||
1786 | return rc; | ||
1787 | } | ||
1788 | |||
1789 | static void | ||
1790 | smb3_free_transform_rq(struct smb_rqst *rqst) | ||
1791 | { | ||
1792 | int i = rqst->rq_npages - 1; | ||
1793 | |||
1794 | for (; i >= 0; i--) | ||
1795 | put_page(rqst->rq_pages[i]); | ||
1796 | kfree(rqst->rq_pages); | ||
1797 | /* free transform header */ | ||
1798 | kfree(rqst->rq_iov[0].iov_base); | ||
1799 | kfree(rqst->rq_iov); | ||
1800 | } | ||
1801 | |||
1802 | static int | ||
1803 | smb3_is_transform_hdr(void *buf) | ||
1804 | { | ||
1805 | struct smb2_transform_hdr *trhdr = buf; | ||
1806 | |||
1807 | return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM; | ||
1808 | } | ||
1809 | |||
1810 | static int | ||
1811 | decrypt_raw_data(struct TCP_Server_Info *server, char *buf, | ||
1812 | unsigned int buf_data_size, struct page **pages, | ||
1813 | unsigned int npages, unsigned int page_data_size) | ||
1814 | { | ||
1815 | struct kvec iov[2]; | ||
1816 | struct smb_rqst rqst = {NULL}; | ||
1817 | struct smb2_hdr *hdr; | ||
1818 | int rc; | ||
1819 | |||
1820 | iov[0].iov_base = buf; | ||
1821 | iov[0].iov_len = sizeof(struct smb2_transform_hdr); | ||
1822 | iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); | ||
1823 | iov[1].iov_len = buf_data_size; | ||
1824 | |||
1825 | rqst.rq_iov = iov; | ||
1826 | rqst.rq_nvec = 2; | ||
1827 | rqst.rq_pages = pages; | ||
1828 | rqst.rq_npages = npages; | ||
1829 | rqst.rq_pagesz = PAGE_SIZE; | ||
1830 | rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; | ||
1831 | |||
1832 | rc = crypt_message(server, &rqst, 0); | ||
1833 | cifs_dbg(FYI, "decrypt message returned %d\n", rc); | ||
1834 | |||
1835 | if (rc) | ||
1836 | return rc; | ||
1837 | |||
1838 | memmove(buf + 4, iov[1].iov_base, buf_data_size); | ||
1839 | hdr = (struct smb2_hdr *)buf; | ||
1840 | hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size); | ||
1841 | server->total_read = buf_data_size + page_data_size + 4; | ||
1842 | |||
1843 | return rc; | ||
1844 | } | ||
1845 | |||
1846 | static int | ||
1847 | read_data_into_pages(struct TCP_Server_Info *server, struct page **pages, | ||
1848 | unsigned int npages, unsigned int len) | ||
1849 | { | ||
1850 | int i; | ||
1851 | int length; | ||
1852 | |||
1853 | for (i = 0; i < npages; i++) { | ||
1854 | struct page *page = pages[i]; | ||
1855 | size_t n; | ||
1856 | |||
1857 | n = len; | ||
1858 | if (len >= PAGE_SIZE) { | ||
1859 | /* enough data to fill the page */ | ||
1860 | n = PAGE_SIZE; | ||
1861 | len -= n; | ||
1862 | } else { | ||
1863 | zero_user(page, len, PAGE_SIZE - len); | ||
1864 | len = 0; | ||
1865 | } | ||
1866 | length = cifs_read_page_from_socket(server, page, n); | ||
1867 | if (length < 0) | ||
1868 | return length; | ||
1869 | server->total_read += length; | ||
1870 | } | ||
1871 | |||
1872 | return 0; | ||
1873 | } | ||
1874 | |||
1875 | static int | ||
1876 | init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size, | ||
1877 | unsigned int cur_off, struct bio_vec **page_vec) | ||
1878 | { | ||
1879 | struct bio_vec *bvec; | ||
1880 | int i; | ||
1881 | |||
1882 | bvec = kcalloc(npages, sizeof(struct bio_vec), GFP_KERNEL); | ||
1883 | if (!bvec) | ||
1884 | return -ENOMEM; | ||
1885 | |||
1886 | for (i = 0; i < npages; i++) { | ||
1887 | bvec[i].bv_page = pages[i]; | ||
1888 | bvec[i].bv_offset = (i == 0) ? cur_off : 0; | ||
1889 | bvec[i].bv_len = min_t(unsigned int, PAGE_SIZE, data_size); | ||
1890 | data_size -= bvec[i].bv_len; | ||
1891 | } | ||
1892 | |||
1893 | if (data_size != 0) { | ||
1894 | cifs_dbg(VFS, "%s: something went wrong\n", __func__); | ||
1895 | kfree(bvec); | ||
1896 | return -EIO; | ||
1897 | } | ||
1898 | |||
1899 | *page_vec = bvec; | ||
1900 | return 0; | ||
1901 | } | ||
1902 | |||
1903 | static int | ||
1904 | handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | ||
1905 | char *buf, unsigned int buf_len, struct page **pages, | ||
1906 | unsigned int npages, unsigned int page_data_size) | ||
1907 | { | ||
1908 | unsigned int data_offset; | ||
1909 | unsigned int data_len; | ||
1910 | unsigned int cur_off; | ||
1911 | unsigned int cur_page_idx; | ||
1912 | unsigned int pad_len; | ||
1913 | struct cifs_readdata *rdata = mid->callback_data; | ||
1914 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | ||
1915 | struct bio_vec *bvec = NULL; | ||
1916 | struct iov_iter iter; | ||
1917 | struct kvec iov; | ||
1918 | int length; | ||
1919 | |||
1920 | if (shdr->Command != SMB2_READ) { | ||
1921 | cifs_dbg(VFS, "only big read responses are supported\n"); | ||
1922 | return -ENOTSUPP; | ||
1923 | } | ||
1924 | |||
1925 | if (server->ops->is_status_pending && | ||
1926 | server->ops->is_status_pending(buf, server, 0)) | ||
1927 | return -1; | ||
1928 | |||
1929 | rdata->result = server->ops->map_error(buf, false); | ||
1930 | if (rdata->result != 0) { | ||
1931 | cifs_dbg(FYI, "%s: server returned error %d\n", | ||
1932 | __func__, rdata->result); | ||
1933 | dequeue_mid(mid, rdata->result); | ||
1934 | return 0; | ||
1935 | } | ||
1936 | |||
1937 | data_offset = server->ops->read_data_offset(buf) + 4; | ||
1938 | data_len = server->ops->read_data_length(buf); | ||
1939 | |||
1940 | if (data_offset < server->vals->read_rsp_size) { | ||
1941 | /* | ||
1942 | * win2k8 sometimes sends an offset of 0 when the read | ||
1943 | * is beyond the EOF. Treat it as if the data starts just after | ||
1944 | * the header. | ||
1945 | */ | ||
1946 | cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n", | ||
1947 | __func__, data_offset); | ||
1948 | data_offset = server->vals->read_rsp_size; | ||
1949 | } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { | ||
1950 | /* data_offset is beyond the end of smallbuf */ | ||
1951 | cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", | ||
1952 | __func__, data_offset); | ||
1953 | rdata->result = -EIO; | ||
1954 | dequeue_mid(mid, rdata->result); | ||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | pad_len = data_offset - server->vals->read_rsp_size; | ||
1959 | |||
1960 | if (buf_len <= data_offset) { | ||
1961 | /* read response payload is in pages */ | ||
1962 | cur_page_idx = pad_len / PAGE_SIZE; | ||
1963 | cur_off = pad_len % PAGE_SIZE; | ||
1964 | |||
1965 | if (cur_page_idx != 0) { | ||
1966 | /* data offset is beyond the 1st page of response */ | ||
1967 | cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n", | ||
1968 | __func__, data_offset); | ||
1969 | rdata->result = -EIO; | ||
1970 | dequeue_mid(mid, rdata->result); | ||
1971 | return 0; | ||
1972 | } | ||
1973 | |||
1974 | if (data_len > page_data_size - pad_len) { | ||
1975 | /* data_len is corrupt -- discard frame */ | ||
1976 | rdata->result = -EIO; | ||
1977 | dequeue_mid(mid, rdata->result); | ||
1978 | return 0; | ||
1979 | } | ||
1980 | |||
1981 | rdata->result = init_read_bvec(pages, npages, page_data_size, | ||
1982 | cur_off, &bvec); | ||
1983 | if (rdata->result != 0) { | ||
1984 | dequeue_mid(mid, rdata->result); | ||
1985 | return 0; | ||
1986 | } | ||
1987 | |||
1988 | iov_iter_bvec(&iter, WRITE | ITER_BVEC, bvec, npages, data_len); | ||
1989 | } else if (buf_len >= data_offset + data_len) { | ||
1990 | /* read response payload is in buf */ | ||
1991 | WARN_ONCE(npages > 0, "read data can be either in buf or in pages"); | ||
1992 | iov.iov_base = buf + data_offset; | ||
1993 | iov.iov_len = data_len; | ||
1994 | iov_iter_kvec(&iter, WRITE | ITER_KVEC, &iov, 1, data_len); | ||
1995 | } else { | ||
1996 | /* read response payload cannot be in both buf and pages */ | ||
1997 | WARN_ONCE(1, "buf can not contain only a part of read data"); | ||
1998 | rdata->result = -EIO; | ||
1999 | dequeue_mid(mid, rdata->result); | ||
2000 | return 0; | ||
2001 | } | ||
2002 | |||
2003 | /* set up first iov for signature check */ | ||
2004 | rdata->iov[0].iov_base = buf; | ||
2005 | rdata->iov[0].iov_len = 4; | ||
2006 | rdata->iov[1].iov_base = buf + 4; | ||
2007 | rdata->iov[1].iov_len = server->vals->read_rsp_size - 4; | ||
2008 | cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", | ||
2009 | rdata->iov[0].iov_base, server->vals->read_rsp_size); | ||
2010 | |||
2011 | length = rdata->copy_into_pages(server, rdata, &iter); | ||
2012 | |||
2013 | kfree(bvec); | ||
2014 | |||
2015 | if (length < 0) | ||
2016 | return length; | ||
2017 | |||
2018 | dequeue_mid(mid, false); | ||
2019 | return length; | ||
2020 | } | ||
2021 | |||
2022 | static int | ||
2023 | receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | ||
2024 | { | ||
2025 | char *buf = server->smallbuf; | ||
2026 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; | ||
2027 | unsigned int npages; | ||
2028 | struct page **pages; | ||
2029 | unsigned int len; | ||
2030 | unsigned int buflen = get_rfc1002_length(buf) + 4; | ||
2031 | int rc; | ||
2032 | int i = 0; | ||
2033 | |||
2034 | len = min_t(unsigned int, buflen, server->vals->read_rsp_size - 4 + | ||
2035 | sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; | ||
2036 | |||
2037 | rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); | ||
2038 | if (rc < 0) | ||
2039 | return rc; | ||
2040 | server->total_read += rc; | ||
2041 | |||
2042 | len = le32_to_cpu(tr_hdr->OriginalMessageSize) + 4 - | ||
2043 | server->vals->read_rsp_size; | ||
2044 | npages = DIV_ROUND_UP(len, PAGE_SIZE); | ||
2045 | |||
2046 | pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); | ||
2047 | if (!pages) { | ||
2048 | rc = -ENOMEM; | ||
2049 | goto discard_data; | ||
2050 | } | ||
2051 | |||
2052 | for (; i < npages; i++) { | ||
2053 | pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); | ||
2054 | if (!pages[i]) { | ||
2055 | rc = -ENOMEM; | ||
2056 | goto discard_data; | ||
2057 | } | ||
2058 | } | ||
2059 | |||
2060 | /* read read data into pages */ | ||
2061 | rc = read_data_into_pages(server, pages, npages, len); | ||
2062 | if (rc) | ||
2063 | goto free_pages; | ||
2064 | |||
2065 | rc = cifs_discard_remaining_data(server); | ||
2066 | if (rc) | ||
2067 | goto free_pages; | ||
2068 | |||
2069 | rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - 4, | ||
2070 | pages, npages, len); | ||
2071 | if (rc) | ||
2072 | goto free_pages; | ||
2073 | |||
2074 | *mid = smb2_find_mid(server, buf); | ||
2075 | if (*mid == NULL) | ||
2076 | cifs_dbg(FYI, "mid not found\n"); | ||
2077 | else { | ||
2078 | cifs_dbg(FYI, "mid found\n"); | ||
2079 | (*mid)->decrypted = true; | ||
2080 | rc = handle_read_data(server, *mid, buf, | ||
2081 | server->vals->read_rsp_size, | ||
2082 | pages, npages, len); | ||
2083 | } | ||
2084 | |||
2085 | free_pages: | ||
2086 | for (i = i - 1; i >= 0; i--) | ||
2087 | put_page(pages[i]); | ||
2088 | kfree(pages); | ||
2089 | return rc; | ||
2090 | discard_data: | ||
2091 | cifs_discard_remaining_data(server); | ||
2092 | goto free_pages; | ||
2093 | } | ||
2094 | |||
2095 | static int | ||
2096 | receive_encrypted_standard(struct TCP_Server_Info *server, | ||
2097 | struct mid_q_entry **mid) | ||
2098 | { | ||
2099 | int length; | ||
2100 | char *buf = server->smallbuf; | ||
2101 | unsigned int pdu_length = get_rfc1002_length(buf); | ||
2102 | unsigned int buf_size; | ||
2103 | struct mid_q_entry *mid_entry; | ||
2104 | |||
2105 | /* switch to large buffer if too big for a small one */ | ||
2106 | if (pdu_length + 4 > MAX_CIFS_SMALL_BUFFER_SIZE) { | ||
2107 | server->large_buf = true; | ||
2108 | memcpy(server->bigbuf, buf, server->total_read); | ||
2109 | buf = server->bigbuf; | ||
2110 | } | ||
2111 | |||
2112 | /* now read the rest */ | ||
2113 | length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, | ||
2114 | pdu_length - HEADER_SIZE(server) + 1 + 4); | ||
2115 | if (length < 0) | ||
2116 | return length; | ||
2117 | server->total_read += length; | ||
2118 | |||
2119 | buf_size = pdu_length + 4 - sizeof(struct smb2_transform_hdr); | ||
2120 | length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0); | ||
2121 | if (length) | ||
2122 | return length; | ||
2123 | |||
2124 | mid_entry = smb2_find_mid(server, buf); | ||
2125 | if (mid_entry == NULL) | ||
2126 | cifs_dbg(FYI, "mid not found\n"); | ||
2127 | else { | ||
2128 | cifs_dbg(FYI, "mid found\n"); | ||
2129 | mid_entry->decrypted = true; | ||
2130 | } | ||
2131 | |||
2132 | *mid = mid_entry; | ||
2133 | |||
2134 | if (mid_entry && mid_entry->handle) | ||
2135 | return mid_entry->handle(server, mid_entry); | ||
2136 | |||
2137 | return cifs_handle_standard(server, mid_entry); | ||
2138 | } | ||
2139 | |||
2140 | static int | ||
2141 | smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) | ||
2142 | { | ||
2143 | char *buf = server->smallbuf; | ||
2144 | unsigned int pdu_length = get_rfc1002_length(buf); | ||
2145 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; | ||
2146 | unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); | ||
2147 | |||
2148 | if (pdu_length + 4 < sizeof(struct smb2_transform_hdr) + | ||
2149 | sizeof(struct smb2_sync_hdr)) { | ||
2150 | cifs_dbg(VFS, "Transform message is too small (%u)\n", | ||
2151 | pdu_length); | ||
2152 | cifs_reconnect(server); | ||
2153 | wake_up(&server->response_q); | ||
2154 | return -ECONNABORTED; | ||
2155 | } | ||
2156 | |||
2157 | if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) { | ||
2158 | cifs_dbg(VFS, "Transform message is broken\n"); | ||
2159 | cifs_reconnect(server); | ||
2160 | wake_up(&server->response_q); | ||
2161 | return -ECONNABORTED; | ||
2162 | } | ||
2163 | |||
2164 | if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) | ||
2165 | return receive_encrypted_read(server, mid); | ||
2166 | |||
2167 | return receive_encrypted_standard(server, mid); | ||
2168 | } | ||
2169 | |||
2170 | int | ||
2171 | smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid) | ||
2172 | { | ||
2173 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; | ||
2174 | |||
2175 | return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 4, | ||
2176 | NULL, 0, 0); | ||
2177 | } | ||
2178 | |||
1548 | struct smb_version_operations smb20_operations = { | 2179 | struct smb_version_operations smb20_operations = { |
1549 | .compare_fids = smb2_compare_fids, | 2180 | .compare_fids = smb2_compare_fids, |
1550 | .setup_request = smb2_setup_request, | 2181 | .setup_request = smb2_setup_request, |
@@ -1791,6 +2422,10 @@ struct smb_version_operations smb30_operations = { | |||
1791 | .dir_needs_close = smb2_dir_needs_close, | 2422 | .dir_needs_close = smb2_dir_needs_close, |
1792 | .fallocate = smb3_fallocate, | 2423 | .fallocate = smb3_fallocate, |
1793 | .enum_snapshots = smb3_enum_snapshots, | 2424 | .enum_snapshots = smb3_enum_snapshots, |
2425 | .init_transform_rq = smb3_init_transform_rq, | ||
2426 | .free_transform_rq = smb3_free_transform_rq, | ||
2427 | .is_transform_hdr = smb3_is_transform_hdr, | ||
2428 | .receive_transform = smb3_receive_transform, | ||
1794 | }; | 2429 | }; |
1795 | 2430 | ||
1796 | #ifdef CONFIG_CIFS_SMB311 | 2431 | #ifdef CONFIG_CIFS_SMB311 |
@@ -1879,6 +2514,10 @@ struct smb_version_operations smb311_operations = { | |||
1879 | .dir_needs_close = smb2_dir_needs_close, | 2514 | .dir_needs_close = smb2_dir_needs_close, |
1880 | .fallocate = smb3_fallocate, | 2515 | .fallocate = smb3_fallocate, |
1881 | .enum_snapshots = smb3_enum_snapshots, | 2516 | .enum_snapshots = smb3_enum_snapshots, |
2517 | .init_transform_rq = smb3_init_transform_rq, | ||
2518 | .free_transform_rq = smb3_free_transform_rq, | ||
2519 | .is_transform_hdr = smb3_is_transform_hdr, | ||
2520 | .receive_transform = smb3_receive_transform, | ||
1882 | }; | 2521 | }; |
1883 | #endif /* CIFS_SMB311 */ | 2522 | #endif /* CIFS_SMB311 */ |
1884 | 2523 | ||
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 87457227812c..ad83b3db2840 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -77,45 +77,42 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
77 | /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */ | 77 | /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */ |
78 | }; | 78 | }; |
79 | 79 | ||
80 | static int encryption_required(const struct cifs_tcon *tcon) | ||
81 | { | ||
82 | if (!tcon) | ||
83 | return 0; | ||
84 | if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || | ||
85 | (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) | ||
86 | return 1; | ||
87 | if (tcon->seal && | ||
88 | (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) | ||
89 | return 1; | ||
90 | return 0; | ||
91 | } | ||
80 | 92 | ||
81 | static void | 93 | static void |
82 | smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , | 94 | smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, |
83 | const struct cifs_tcon *tcon) | 95 | const struct cifs_tcon *tcon) |
84 | { | 96 | { |
85 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 97 | shdr->ProtocolId = SMB2_PROTO_NUMBER; |
86 | char *temp = (char *)hdr; | 98 | shdr->StructureSize = cpu_to_le16(64); |
87 | /* lookup word count ie StructureSize from table */ | 99 | shdr->Command = smb2_cmd; |
88 | __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)]; | ||
89 | |||
90 | /* | ||
91 | * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of | ||
92 | * largest operations (Create) | ||
93 | */ | ||
94 | memset(temp, 0, 256); | ||
95 | |||
96 | /* Note this is only network field converted to big endian */ | ||
97 | hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr) | ||
98 | - 4 /* RFC 1001 length field itself not counted */); | ||
99 | |||
100 | hdr->ProtocolId = SMB2_PROTO_NUMBER; | ||
101 | hdr->StructureSize = cpu_to_le16(64); | ||
102 | hdr->Command = smb2_cmd; | ||
103 | if (tcon && tcon->ses && tcon->ses->server) { | 100 | if (tcon && tcon->ses && tcon->ses->server) { |
104 | struct TCP_Server_Info *server = tcon->ses->server; | 101 | struct TCP_Server_Info *server = tcon->ses->server; |
105 | 102 | ||
106 | spin_lock(&server->req_lock); | 103 | spin_lock(&server->req_lock); |
107 | /* Request up to 2 credits but don't go over the limit. */ | 104 | /* Request up to 2 credits but don't go over the limit. */ |
108 | if (server->credits >= server->max_credits) | 105 | if (server->credits >= server->max_credits) |
109 | hdr->CreditRequest = cpu_to_le16(0); | 106 | shdr->CreditRequest = cpu_to_le16(0); |
110 | else | 107 | else |
111 | hdr->CreditRequest = cpu_to_le16( | 108 | shdr->CreditRequest = cpu_to_le16( |
112 | min_t(int, server->max_credits - | 109 | min_t(int, server->max_credits - |
113 | server->credits, 2)); | 110 | server->credits, 2)); |
114 | spin_unlock(&server->req_lock); | 111 | spin_unlock(&server->req_lock); |
115 | } else { | 112 | } else { |
116 | hdr->CreditRequest = cpu_to_le16(2); | 113 | shdr->CreditRequest = cpu_to_le16(2); |
117 | } | 114 | } |
118 | hdr->ProcessId = cpu_to_le32((__u16)current->tgid); | 115 | shdr->ProcessId = cpu_to_le32((__u16)current->tgid); |
119 | 116 | ||
120 | if (!tcon) | 117 | if (!tcon) |
121 | goto out; | 118 | goto out; |
@@ -124,13 +121,13 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , | |||
124 | /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ | 121 | /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ |
125 | if ((tcon->ses) && (tcon->ses->server) && | 122 | if ((tcon->ses) && (tcon->ses->server) && |
126 | (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) | 123 | (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) |
127 | hdr->CreditCharge = cpu_to_le16(1); | 124 | shdr->CreditCharge = cpu_to_le16(1); |
128 | /* else CreditCharge MBZ */ | 125 | /* else CreditCharge MBZ */ |
129 | 126 | ||
130 | hdr->TreeId = tcon->tid; | 127 | shdr->TreeId = tcon->tid; |
131 | /* Uid is not converted */ | 128 | /* Uid is not converted */ |
132 | if (tcon->ses) | 129 | if (tcon->ses) |
133 | hdr->SessionId = tcon->ses->Suid; | 130 | shdr->SessionId = tcon->ses->Suid; |
134 | 131 | ||
135 | /* | 132 | /* |
136 | * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have | 133 | * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have |
@@ -143,12 +140,12 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , | |||
143 | * but it is safer to net set it for now. | 140 | * but it is safer to net set it for now. |
144 | */ | 141 | */ |
145 | /* if (tcon->share_flags & SHI1005_FLAGS_DFS) | 142 | /* if (tcon->share_flags & SHI1005_FLAGS_DFS) |
146 | hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ | 143 | shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ |
147 | 144 | ||
148 | if (tcon->ses && tcon->ses->server && tcon->ses->server->sign) | 145 | if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && |
149 | hdr->Flags |= SMB2_FLAGS_SIGNED; | 146 | !encryption_required(tcon)) |
147 | shdr->Flags |= SMB2_FLAGS_SIGNED; | ||
150 | out: | 148 | out: |
151 | pdu->StructureSize2 = cpu_to_le16(parmsize); | ||
152 | return; | 149 | return; |
153 | } | 150 | } |
154 | 151 | ||
@@ -289,16 +286,74 @@ out: | |||
289 | return rc; | 286 | return rc; |
290 | } | 287 | } |
291 | 288 | ||
289 | static void | ||
290 | fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, | ||
291 | unsigned int *total_len) | ||
292 | { | ||
293 | struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; | ||
294 | /* lookup word count ie StructureSize from table */ | ||
295 | __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)]; | ||
296 | |||
297 | /* | ||
298 | * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of | ||
299 | * largest operations (Create) | ||
300 | */ | ||
301 | memset(buf, 0, 256); | ||
302 | |||
303 | smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon); | ||
304 | spdu->StructureSize2 = cpu_to_le16(parmsize); | ||
305 | |||
306 | *total_len = parmsize + sizeof(struct smb2_sync_hdr); | ||
307 | } | ||
308 | |||
309 | /* init request without RFC1001 length at the beginning */ | ||
310 | static int | ||
311 | smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, | ||
312 | void **request_buf, unsigned int *total_len) | ||
313 | { | ||
314 | int rc; | ||
315 | struct smb2_sync_hdr *shdr; | ||
316 | |||
317 | rc = smb2_reconnect(smb2_command, tcon); | ||
318 | if (rc) | ||
319 | return rc; | ||
320 | |||
321 | /* BB eventually switch this to SMB2 specific small buf size */ | ||
322 | *request_buf = cifs_small_buf_get(); | ||
323 | if (*request_buf == NULL) { | ||
324 | /* BB should we add a retry in here if not a writepage? */ | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | |||
328 | shdr = (struct smb2_sync_hdr *)(*request_buf); | ||
329 | |||
330 | fill_small_buf(smb2_command, tcon, shdr, total_len); | ||
331 | |||
332 | if (tcon != NULL) { | ||
333 | #ifdef CONFIG_CIFS_STATS2 | ||
334 | uint16_t com_code = le16_to_cpu(smb2_command); | ||
335 | |||
336 | cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]); | ||
337 | #endif | ||
338 | cifs_stats_inc(&tcon->num_smbs_sent); | ||
339 | } | ||
340 | |||
341 | return rc; | ||
342 | } | ||
343 | |||
292 | /* | 344 | /* |
293 | * Allocate and return pointer to an SMB request hdr, and set basic | 345 | * Allocate and return pointer to an SMB request hdr, and set basic |
294 | * SMB information in the SMB header. If the return code is zero, this | 346 | * SMB information in the SMB header. If the return code is zero, this |
295 | * function must have filled in request_buf pointer. | 347 | * function must have filled in request_buf pointer. The returned buffer |
348 | * has RFC1001 length at the beginning. | ||
296 | */ | 349 | */ |
297 | static int | 350 | static int |
298 | small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon, | 351 | small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon, |
299 | void **request_buf) | 352 | void **request_buf) |
300 | { | 353 | { |
301 | int rc = 0; | 354 | int rc; |
355 | unsigned int total_len; | ||
356 | struct smb2_pdu *pdu; | ||
302 | 357 | ||
303 | rc = smb2_reconnect(smb2_command, tcon); | 358 | rc = smb2_reconnect(smb2_command, tcon); |
304 | if (rc) | 359 | if (rc) |
@@ -311,7 +366,12 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon, | |||
311 | return -ENOMEM; | 366 | return -ENOMEM; |
312 | } | 367 | } |
313 | 368 | ||
314 | smb2_hdr_assemble((struct smb2_hdr *) *request_buf, smb2_command, tcon); | 369 | pdu = (struct smb2_pdu *)(*request_buf); |
370 | |||
371 | fill_small_buf(smb2_command, tcon, get_sync_hdr(pdu), &total_len); | ||
372 | |||
373 | /* Note this is only network field converted to big endian */ | ||
374 | pdu->hdr.smb2_buf_length = cpu_to_be32(total_len); | ||
315 | 375 | ||
316 | if (tcon != NULL) { | 376 | if (tcon != NULL) { |
317 | #ifdef CONFIG_CIFS_STATS2 | 377 | #ifdef CONFIG_CIFS_STATS2 |
@@ -376,7 +436,6 @@ static void assemble_neg_contexts(struct smb2_negotiate_req *req) | |||
376 | } | 436 | } |
377 | #endif /* SMB311 */ | 437 | #endif /* SMB311 */ |
378 | 438 | ||
379 | |||
380 | /* | 439 | /* |
381 | * | 440 | * |
382 | * SMB2 Worker functions follow: | 441 | * SMB2 Worker functions follow: |
@@ -398,6 +457,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
398 | struct smb2_negotiate_req *req; | 457 | struct smb2_negotiate_req *req; |
399 | struct smb2_negotiate_rsp *rsp; | 458 | struct smb2_negotiate_rsp *rsp; |
400 | struct kvec iov[1]; | 459 | struct kvec iov[1]; |
460 | struct kvec rsp_iov; | ||
401 | int rc = 0; | 461 | int rc = 0; |
402 | int resp_buftype; | 462 | int resp_buftype; |
403 | struct TCP_Server_Info *server = ses->server; | 463 | struct TCP_Server_Info *server = ses->server; |
@@ -416,7 +476,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
416 | if (rc) | 476 | if (rc) |
417 | return rc; | 477 | return rc; |
418 | 478 | ||
419 | req->hdr.SessionId = 0; | 479 | req->hdr.sync_hdr.SessionId = 0; |
420 | 480 | ||
421 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); | 481 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
422 | 482 | ||
@@ -446,9 +506,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
446 | /* 4 for rfc1002 length field */ | 506 | /* 4 for rfc1002 length field */ |
447 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 507 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
448 | 508 | ||
449 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags); | 509 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); |
450 | 510 | cifs_small_buf_release(req); | |
451 | rsp = (struct smb2_negotiate_rsp *)iov[0].iov_base; | 511 | rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base; |
452 | /* | 512 | /* |
453 | * No tcon so can't do | 513 | * No tcon so can't do |
454 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); | 514 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); |
@@ -627,14 +687,15 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) | |||
627 | if (rc) | 687 | if (rc) |
628 | return rc; | 688 | return rc; |
629 | 689 | ||
630 | req->hdr.SessionId = 0; /* First session, not a reauthenticate */ | 690 | /* First session, not a reauthenticate */ |
691 | req->hdr.sync_hdr.SessionId = 0; | ||
631 | 692 | ||
632 | /* if reconnect, we need to send previous sess id, otherwise it is 0 */ | 693 | /* if reconnect, we need to send previous sess id, otherwise it is 0 */ |
633 | req->PreviousSessionId = sess_data->previous_session; | 694 | req->PreviousSessionId = sess_data->previous_session; |
634 | 695 | ||
635 | req->Flags = 0; /* MBZ */ | 696 | req->Flags = 0; /* MBZ */ |
636 | /* to enable echos and oplocks */ | 697 | /* to enable echos and oplocks */ |
637 | req->hdr.CreditRequest = cpu_to_le16(3); | 698 | req->hdr.sync_hdr.CreditRequest = cpu_to_le16(3); |
638 | 699 | ||
639 | /* only one of SMB2 signing flags may be set in SMB2 request */ | 700 | /* only one of SMB2 signing flags may be set in SMB2 request */ |
640 | if (server->sign) | 701 | if (server->sign) |
@@ -671,6 +732,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) | |||
671 | { | 732 | { |
672 | int rc; | 733 | int rc; |
673 | struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base; | 734 | struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base; |
735 | struct kvec rsp_iov = { NULL, 0 }; | ||
674 | 736 | ||
675 | /* Testing shows that buffer offset must be at location of Buffer[0] */ | 737 | /* Testing shows that buffer offset must be at location of Buffer[0] */ |
676 | req->SecurityBufferOffset = | 738 | req->SecurityBufferOffset = |
@@ -685,7 +747,9 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) | |||
685 | rc = SendReceive2(sess_data->xid, sess_data->ses, | 747 | rc = SendReceive2(sess_data->xid, sess_data->ses, |
686 | sess_data->iov, 2, | 748 | sess_data->iov, 2, |
687 | &sess_data->buf0_type, | 749 | &sess_data->buf0_type, |
688 | CIFS_LOG_ERROR | CIFS_NEG_OP); | 750 | CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov); |
751 | cifs_small_buf_release(sess_data->iov[0].iov_base); | ||
752 | memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec)); | ||
689 | 753 | ||
690 | return rc; | 754 | return rc; |
691 | } | 755 | } |
@@ -697,15 +761,13 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data) | |||
697 | struct cifs_ses *ses = sess_data->ses; | 761 | struct cifs_ses *ses = sess_data->ses; |
698 | 762 | ||
699 | mutex_lock(&ses->server->srv_mutex); | 763 | mutex_lock(&ses->server->srv_mutex); |
700 | if (ses->server->sign && ses->server->ops->generate_signingkey) { | 764 | if (ses->server->ops->generate_signingkey) { |
701 | rc = ses->server->ops->generate_signingkey(ses); | 765 | rc = ses->server->ops->generate_signingkey(ses); |
702 | kfree(ses->auth_key.response); | ||
703 | ses->auth_key.response = NULL; | ||
704 | if (rc) { | 766 | if (rc) { |
705 | cifs_dbg(FYI, | 767 | cifs_dbg(FYI, |
706 | "SMB3 session key generation failed\n"); | 768 | "SMB3 session key generation failed\n"); |
707 | mutex_unlock(&ses->server->srv_mutex); | 769 | mutex_unlock(&ses->server->srv_mutex); |
708 | goto keygen_exit; | 770 | return rc; |
709 | } | 771 | } |
710 | } | 772 | } |
711 | if (!ses->server->session_estab) { | 773 | if (!ses->server->session_estab) { |
@@ -719,12 +781,6 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data) | |||
719 | ses->status = CifsGood; | 781 | ses->status = CifsGood; |
720 | ses->need_reconnect = false; | 782 | ses->need_reconnect = false; |
721 | spin_unlock(&GlobalMid_Lock); | 783 | spin_unlock(&GlobalMid_Lock); |
722 | |||
723 | keygen_exit: | ||
724 | if (!ses->server->sign) { | ||
725 | kfree(ses->auth_key.response); | ||
726 | ses->auth_key.response = NULL; | ||
727 | } | ||
728 | return rc; | 784 | return rc; |
729 | } | 785 | } |
730 | 786 | ||
@@ -781,11 +837,9 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) | |||
781 | goto out_put_spnego_key; | 837 | goto out_put_spnego_key; |
782 | 838 | ||
783 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; | 839 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
784 | ses->Suid = rsp->hdr.SessionId; | 840 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
785 | 841 | ||
786 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 842 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
787 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
788 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
789 | 843 | ||
790 | rc = SMB2_sess_establish_session(sess_data); | 844 | rc = SMB2_sess_establish_session(sess_data); |
791 | out_put_spnego_key: | 845 | out_put_spnego_key: |
@@ -859,7 +913,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) | |||
859 | 913 | ||
860 | /* If true, rc here is expected and not an error */ | 914 | /* If true, rc here is expected and not an error */ |
861 | if (sess_data->buf0_type != CIFS_NO_BUFFER && | 915 | if (sess_data->buf0_type != CIFS_NO_BUFFER && |
862 | rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) | 916 | rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) |
863 | rc = 0; | 917 | rc = 0; |
864 | 918 | ||
865 | if (rc) | 919 | if (rc) |
@@ -880,10 +934,8 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) | |||
880 | cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); | 934 | cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); |
881 | 935 | ||
882 | 936 | ||
883 | ses->Suid = rsp->hdr.SessionId; | 937 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
884 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 938 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
885 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
886 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
887 | 939 | ||
888 | out: | 940 | out: |
889 | kfree(ntlmssp_blob); | 941 | kfree(ntlmssp_blob); |
@@ -916,7 +968,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) | |||
916 | goto out; | 968 | goto out; |
917 | 969 | ||
918 | req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; | 970 | req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; |
919 | req->hdr.SessionId = ses->Suid; | 971 | req->hdr.sync_hdr.SessionId = ses->Suid; |
920 | 972 | ||
921 | rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, | 973 | rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, |
922 | sess_data->nls_cp); | 974 | sess_data->nls_cp); |
@@ -940,10 +992,8 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) | |||
940 | 992 | ||
941 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; | 993 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
942 | 994 | ||
943 | ses->Suid = rsp->hdr.SessionId; | 995 | ses->Suid = rsp->hdr.sync_hdr.SessionId; |
944 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 996 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
945 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | ||
946 | cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); | ||
947 | 997 | ||
948 | rc = SMB2_sess_establish_session(sess_data); | 998 | rc = SMB2_sess_establish_session(sess_data); |
949 | out: | 999 | out: |
@@ -1018,6 +1068,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) | |||
1018 | struct smb2_logoff_req *req; /* response is also trivial struct */ | 1068 | struct smb2_logoff_req *req; /* response is also trivial struct */ |
1019 | int rc = 0; | 1069 | int rc = 0; |
1020 | struct TCP_Server_Info *server; | 1070 | struct TCP_Server_Info *server; |
1071 | int flags = 0; | ||
1021 | 1072 | ||
1022 | cifs_dbg(FYI, "disconnect session %p\n", ses); | 1073 | cifs_dbg(FYI, "disconnect session %p\n", ses); |
1023 | 1074 | ||
@@ -1035,11 +1086,15 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) | |||
1035 | return rc; | 1086 | return rc; |
1036 | 1087 | ||
1037 | /* since no tcon, smb2_init can not do this, so do here */ | 1088 | /* since no tcon, smb2_init can not do this, so do here */ |
1038 | req->hdr.SessionId = ses->Suid; | 1089 | req->hdr.sync_hdr.SessionId = ses->Suid; |
1039 | if (server->sign) | 1090 | |
1040 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; | 1091 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) |
1092 | flags |= CIFS_TRANSFORM_REQ; | ||
1093 | else if (server->sign) | ||
1094 | req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED; | ||
1041 | 1095 | ||
1042 | rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0); | 1096 | rc = SendReceiveNoRsp(xid, ses, (char *) req, flags); |
1097 | cifs_small_buf_release(req); | ||
1043 | /* | 1098 | /* |
1044 | * No tcon so can't do | 1099 | * No tcon so can't do |
1045 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); | 1100 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); |
@@ -1071,11 +1126,13 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1071 | struct smb2_tree_connect_req *req; | 1126 | struct smb2_tree_connect_req *req; |
1072 | struct smb2_tree_connect_rsp *rsp = NULL; | 1127 | struct smb2_tree_connect_rsp *rsp = NULL; |
1073 | struct kvec iov[2]; | 1128 | struct kvec iov[2]; |
1129 | struct kvec rsp_iov; | ||
1074 | int rc = 0; | 1130 | int rc = 0; |
1075 | int resp_buftype; | 1131 | int resp_buftype; |
1076 | int unc_path_len; | 1132 | int unc_path_len; |
1077 | struct TCP_Server_Info *server; | 1133 | struct TCP_Server_Info *server; |
1078 | __le16 *unc_path = NULL; | 1134 | __le16 *unc_path = NULL; |
1135 | int flags = 0; | ||
1079 | 1136 | ||
1080 | cifs_dbg(FYI, "TCON\n"); | 1137 | cifs_dbg(FYI, "TCON\n"); |
1081 | 1138 | ||
@@ -1087,12 +1144,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1087 | if (tcon && tcon->bad_network_name) | 1144 | if (tcon && tcon->bad_network_name) |
1088 | return -ENOENT; | 1145 | return -ENOENT; |
1089 | 1146 | ||
1090 | if ((tcon && tcon->seal) && | ||
1091 | ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) { | ||
1092 | cifs_dbg(VFS, "encryption requested but no server support"); | ||
1093 | return -EOPNOTSUPP; | ||
1094 | } | ||
1095 | |||
1096 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); | 1147 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); |
1097 | if (unc_path == NULL) | 1148 | if (unc_path == NULL) |
1098 | return -ENOMEM; | 1149 | return -ENOMEM; |
@@ -1111,11 +1162,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1111 | } | 1162 | } |
1112 | 1163 | ||
1113 | if (tcon == NULL) { | 1164 | if (tcon == NULL) { |
1165 | if ((ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)) | ||
1166 | flags |= CIFS_TRANSFORM_REQ; | ||
1167 | |||
1114 | /* since no tcon, smb2_init can not do this, so do here */ | 1168 | /* since no tcon, smb2_init can not do this, so do here */ |
1115 | req->hdr.SessionId = ses->Suid; | 1169 | req->hdr.sync_hdr.SessionId = ses->Suid; |
1116 | /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) | 1170 | /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) |
1117 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ | 1171 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ |
1118 | } | 1172 | } else if (encryption_required(tcon)) |
1173 | flags |= CIFS_TRANSFORM_REQ; | ||
1119 | 1174 | ||
1120 | iov[0].iov_base = (char *)req; | 1175 | iov[0].iov_base = (char *)req; |
1121 | /* 4 for rfc1002 length field and 1 for pad */ | 1176 | /* 4 for rfc1002 length field and 1 for pad */ |
@@ -1130,8 +1185,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1130 | 1185 | ||
1131 | inc_rfc1001_len(req, unc_path_len - 1 /* pad */); | 1186 | inc_rfc1001_len(req, unc_path_len - 1 /* pad */); |
1132 | 1187 | ||
1133 | rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0); | 1188 | rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov); |
1134 | rsp = (struct smb2_tree_connect_rsp *)iov[0].iov_base; | 1189 | cifs_small_buf_release(req); |
1190 | rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; | ||
1135 | 1191 | ||
1136 | if (rc != 0) { | 1192 | if (rc != 0) { |
1137 | if (tcon) { | 1193 | if (tcon) { |
@@ -1142,7 +1198,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1142 | } | 1198 | } |
1143 | 1199 | ||
1144 | if (tcon == NULL) { | 1200 | if (tcon == NULL) { |
1145 | ses->ipc_tid = rsp->hdr.TreeId; | 1201 | ses->ipc_tid = rsp->hdr.sync_hdr.TreeId; |
1146 | goto tcon_exit; | 1202 | goto tcon_exit; |
1147 | } | 1203 | } |
1148 | 1204 | ||
@@ -1165,15 +1221,18 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1165 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); | 1221 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); |
1166 | tcon->tidStatus = CifsGood; | 1222 | tcon->tidStatus = CifsGood; |
1167 | tcon->need_reconnect = false; | 1223 | tcon->need_reconnect = false; |
1168 | tcon->tid = rsp->hdr.TreeId; | 1224 | tcon->tid = rsp->hdr.sync_hdr.TreeId; |
1169 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); | 1225 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
1170 | 1226 | ||
1171 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && | 1227 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
1172 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) | 1228 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
1173 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); | 1229 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
1230 | |||
1231 | if (tcon->seal && | ||
1232 | !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) | ||
1233 | cifs_dbg(VFS, "Encryption is requested but not supported\n"); | ||
1234 | |||
1174 | init_copy_chunk_defaults(tcon); | 1235 | init_copy_chunk_defaults(tcon); |
1175 | if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA) | ||
1176 | cifs_dbg(VFS, "Encrypted shares not supported"); | ||
1177 | if (tcon->ses->server->ops->validate_negotiate) | 1236 | if (tcon->ses->server->ops->validate_negotiate) |
1178 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); | 1237 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); |
1179 | tcon_exit: | 1238 | tcon_exit: |
@@ -1182,7 +1241,7 @@ tcon_exit: | |||
1182 | return rc; | 1241 | return rc; |
1183 | 1242 | ||
1184 | tcon_error_exit: | 1243 | tcon_error_exit: |
1185 | if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { | 1244 | if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
1186 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 1245 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
1187 | if (tcon) | 1246 | if (tcon) |
1188 | tcon->bad_network_name = true; | 1247 | tcon->bad_network_name = true; |
@@ -1197,6 +1256,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) | |||
1197 | int rc = 0; | 1256 | int rc = 0; |
1198 | struct TCP_Server_Info *server; | 1257 | struct TCP_Server_Info *server; |
1199 | struct cifs_ses *ses = tcon->ses; | 1258 | struct cifs_ses *ses = tcon->ses; |
1259 | int flags = 0; | ||
1200 | 1260 | ||
1201 | cifs_dbg(FYI, "Tree Disconnect\n"); | 1261 | cifs_dbg(FYI, "Tree Disconnect\n"); |
1202 | 1262 | ||
@@ -1212,7 +1272,11 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) | |||
1212 | if (rc) | 1272 | if (rc) |
1213 | return rc; | 1273 | return rc; |
1214 | 1274 | ||
1215 | rc = SendReceiveNoRsp(xid, ses, (char *)&req->hdr, 0); | 1275 | if (encryption_required(tcon)) |
1276 | flags |= CIFS_TRANSFORM_REQ; | ||
1277 | |||
1278 | rc = SendReceiveNoRsp(xid, ses, (char *)req, flags); | ||
1279 | cifs_small_buf_release(req); | ||
1216 | if (rc) | 1280 | if (rc) |
1217 | cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); | 1281 | cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); |
1218 | 1282 | ||
@@ -1474,14 +1538,16 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
1474 | struct cifs_tcon *tcon = oparms->tcon; | 1538 | struct cifs_tcon *tcon = oparms->tcon; |
1475 | struct cifs_ses *ses = tcon->ses; | 1539 | struct cifs_ses *ses = tcon->ses; |
1476 | struct kvec iov[4]; | 1540 | struct kvec iov[4]; |
1541 | struct kvec rsp_iov; | ||
1477 | int resp_buftype; | 1542 | int resp_buftype; |
1478 | int uni_path_len; | 1543 | int uni_path_len; |
1479 | __le16 *copy_path = NULL; | 1544 | __le16 *copy_path = NULL; |
1480 | int copy_size; | 1545 | int copy_size; |
1481 | int rc = 0; | 1546 | int rc = 0; |
1482 | unsigned int num_iovecs = 2; | 1547 | unsigned int n_iov = 2; |
1483 | __u32 file_attributes = 0; | 1548 | __u32 file_attributes = 0; |
1484 | char *dhc_buf = NULL, *lc_buf = NULL; | 1549 | char *dhc_buf = NULL, *lc_buf = NULL; |
1550 | int flags = 0; | ||
1485 | 1551 | ||
1486 | cifs_dbg(FYI, "create/open\n"); | 1552 | cifs_dbg(FYI, "create/open\n"); |
1487 | 1553 | ||
@@ -1494,6 +1560,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
1494 | if (rc) | 1560 | if (rc) |
1495 | return rc; | 1561 | return rc; |
1496 | 1562 | ||
1563 | if (encryption_required(tcon)) | ||
1564 | flags |= CIFS_TRANSFORM_REQ; | ||
1565 | |||
1497 | if (oparms->create_options & CREATE_OPTION_READONLY) | 1566 | if (oparms->create_options & CREATE_OPTION_READONLY) |
1498 | file_attributes |= ATTR_READONLY; | 1567 | file_attributes |= ATTR_READONLY; |
1499 | if (oparms->create_options & CREATE_OPTION_SPECIAL) | 1568 | if (oparms->create_options & CREATE_OPTION_SPECIAL) |
@@ -1544,25 +1613,25 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
1544 | *oplock == SMB2_OPLOCK_LEVEL_NONE) | 1613 | *oplock == SMB2_OPLOCK_LEVEL_NONE) |
1545 | req->RequestedOplockLevel = *oplock; | 1614 | req->RequestedOplockLevel = *oplock; |
1546 | else { | 1615 | else { |
1547 | rc = add_lease_context(server, iov, &num_iovecs, oplock); | 1616 | rc = add_lease_context(server, iov, &n_iov, oplock); |
1548 | if (rc) { | 1617 | if (rc) { |
1549 | cifs_small_buf_release(req); | 1618 | cifs_small_buf_release(req); |
1550 | kfree(copy_path); | 1619 | kfree(copy_path); |
1551 | return rc; | 1620 | return rc; |
1552 | } | 1621 | } |
1553 | lc_buf = iov[num_iovecs-1].iov_base; | 1622 | lc_buf = iov[n_iov-1].iov_base; |
1554 | } | 1623 | } |
1555 | 1624 | ||
1556 | if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { | 1625 | if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { |
1557 | /* need to set Next field of lease context if we request it */ | 1626 | /* need to set Next field of lease context if we request it */ |
1558 | if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) { | 1627 | if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) { |
1559 | struct create_context *ccontext = | 1628 | struct create_context *ccontext = |
1560 | (struct create_context *)iov[num_iovecs-1].iov_base; | 1629 | (struct create_context *)iov[n_iov-1].iov_base; |
1561 | ccontext->Next = | 1630 | ccontext->Next = |
1562 | cpu_to_le32(server->vals->create_lease_size); | 1631 | cpu_to_le32(server->vals->create_lease_size); |
1563 | } | 1632 | } |
1564 | 1633 | ||
1565 | rc = add_durable_context(iov, &num_iovecs, oparms, | 1634 | rc = add_durable_context(iov, &n_iov, oparms, |
1566 | tcon->use_persistent); | 1635 | tcon->use_persistent); |
1567 | if (rc) { | 1636 | if (rc) { |
1568 | cifs_small_buf_release(req); | 1637 | cifs_small_buf_release(req); |
@@ -1570,11 +1639,12 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
1570 | kfree(lc_buf); | 1639 | kfree(lc_buf); |
1571 | return rc; | 1640 | return rc; |
1572 | } | 1641 | } |
1573 | dhc_buf = iov[num_iovecs-1].iov_base; | 1642 | dhc_buf = iov[n_iov-1].iov_base; |
1574 | } | 1643 | } |
1575 | 1644 | ||
1576 | rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); | 1645 | rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); |
1577 | rsp = (struct smb2_create_rsp *)iov[0].iov_base; | 1646 | cifs_small_buf_release(req); |
1647 | rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; | ||
1578 | 1648 | ||
1579 | if (rc != 0) { | 1649 | if (rc != 0) { |
1580 | cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); | 1650 | cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); |
@@ -1618,12 +1688,15 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1618 | { | 1688 | { |
1619 | struct smb2_ioctl_req *req; | 1689 | struct smb2_ioctl_req *req; |
1620 | struct smb2_ioctl_rsp *rsp; | 1690 | struct smb2_ioctl_rsp *rsp; |
1691 | struct smb2_sync_hdr *shdr; | ||
1621 | struct TCP_Server_Info *server; | 1692 | struct TCP_Server_Info *server; |
1622 | struct cifs_ses *ses; | 1693 | struct cifs_ses *ses; |
1623 | struct kvec iov[2]; | 1694 | struct kvec iov[2]; |
1695 | struct kvec rsp_iov; | ||
1624 | int resp_buftype; | 1696 | int resp_buftype; |
1625 | int num_iovecs; | 1697 | int n_iov; |
1626 | int rc = 0; | 1698 | int rc = 0; |
1699 | int flags = 0; | ||
1627 | 1700 | ||
1628 | cifs_dbg(FYI, "SMB2 IOCTL\n"); | 1701 | cifs_dbg(FYI, "SMB2 IOCTL\n"); |
1629 | 1702 | ||
@@ -1648,6 +1721,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1648 | if (rc) | 1721 | if (rc) |
1649 | return rc; | 1722 | return rc; |
1650 | 1723 | ||
1724 | if (encryption_required(tcon)) | ||
1725 | flags |= CIFS_TRANSFORM_REQ; | ||
1726 | |||
1651 | req->CtlCode = cpu_to_le32(opcode); | 1727 | req->CtlCode = cpu_to_le32(opcode); |
1652 | req->PersistentFileId = persistent_fid; | 1728 | req->PersistentFileId = persistent_fid; |
1653 | req->VolatileFileId = volatile_fid; | 1729 | req->VolatileFileId = volatile_fid; |
@@ -1659,9 +1735,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1659 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer) - 4); | 1735 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer) - 4); |
1660 | iov[1].iov_base = in_data; | 1736 | iov[1].iov_base = in_data; |
1661 | iov[1].iov_len = indatalen; | 1737 | iov[1].iov_len = indatalen; |
1662 | num_iovecs = 2; | 1738 | n_iov = 2; |
1663 | } else | 1739 | } else |
1664 | num_iovecs = 1; | 1740 | n_iov = 1; |
1665 | 1741 | ||
1666 | req->OutputOffset = 0; | 1742 | req->OutputOffset = 0; |
1667 | req->OutputCount = 0; /* MBZ */ | 1743 | req->OutputCount = 0; /* MBZ */ |
@@ -1698,8 +1774,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1698 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 1774 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
1699 | 1775 | ||
1700 | 1776 | ||
1701 | rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); | 1777 | rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); |
1702 | rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base; | 1778 | cifs_small_buf_release(req); |
1779 | rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; | ||
1703 | 1780 | ||
1704 | if ((rc != 0) && (rc != -EINVAL)) { | 1781 | if ((rc != 0) && (rc != -EINVAL)) { |
1705 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); | 1782 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
@@ -1742,9 +1819,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1742 | goto ioctl_exit; | 1819 | goto ioctl_exit; |
1743 | } | 1820 | } |
1744 | 1821 | ||
1745 | memcpy(*out_data, | 1822 | shdr = get_sync_hdr(rsp); |
1746 | (char *)&rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), | 1823 | memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen); |
1747 | *plen); | ||
1748 | ioctl_exit: | 1824 | ioctl_exit: |
1749 | free_rsp_buf(resp_buftype, rsp); | 1825 | free_rsp_buf(resp_buftype, rsp); |
1750 | return rc; | 1826 | return rc; |
@@ -1784,8 +1860,10 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
1784 | struct TCP_Server_Info *server; | 1860 | struct TCP_Server_Info *server; |
1785 | struct cifs_ses *ses = tcon->ses; | 1861 | struct cifs_ses *ses = tcon->ses; |
1786 | struct kvec iov[1]; | 1862 | struct kvec iov[1]; |
1863 | struct kvec rsp_iov; | ||
1787 | int resp_buftype; | 1864 | int resp_buftype; |
1788 | int rc = 0; | 1865 | int rc = 0; |
1866 | int flags = 0; | ||
1789 | 1867 | ||
1790 | cifs_dbg(FYI, "Close\n"); | 1868 | cifs_dbg(FYI, "Close\n"); |
1791 | 1869 | ||
@@ -1798,6 +1876,9 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
1798 | if (rc) | 1876 | if (rc) |
1799 | return rc; | 1877 | return rc; |
1800 | 1878 | ||
1879 | if (encryption_required(tcon)) | ||
1880 | flags |= CIFS_TRANSFORM_REQ; | ||
1881 | |||
1801 | req->PersistentFileId = persistent_fid; | 1882 | req->PersistentFileId = persistent_fid; |
1802 | req->VolatileFileId = volatile_fid; | 1883 | req->VolatileFileId = volatile_fid; |
1803 | 1884 | ||
@@ -1805,8 +1886,9 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
1805 | /* 4 for rfc1002 length field */ | 1886 | /* 4 for rfc1002 length field */ |
1806 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 1887 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
1807 | 1888 | ||
1808 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0); | 1889 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); |
1809 | rsp = (struct smb2_close_rsp *)iov[0].iov_base; | 1890 | cifs_small_buf_release(req); |
1891 | rsp = (struct smb2_close_rsp *)rsp_iov.iov_base; | ||
1810 | 1892 | ||
1811 | if (rc != 0) { | 1893 | if (rc != 0) { |
1812 | cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); | 1894 | cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); |
@@ -1885,10 +1967,12 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
1885 | struct smb2_query_info_req *req; | 1967 | struct smb2_query_info_req *req; |
1886 | struct smb2_query_info_rsp *rsp = NULL; | 1968 | struct smb2_query_info_rsp *rsp = NULL; |
1887 | struct kvec iov[2]; | 1969 | struct kvec iov[2]; |
1970 | struct kvec rsp_iov; | ||
1888 | int rc = 0; | 1971 | int rc = 0; |
1889 | int resp_buftype; | 1972 | int resp_buftype; |
1890 | struct TCP_Server_Info *server; | 1973 | struct TCP_Server_Info *server; |
1891 | struct cifs_ses *ses = tcon->ses; | 1974 | struct cifs_ses *ses = tcon->ses; |
1975 | int flags = 0; | ||
1892 | 1976 | ||
1893 | cifs_dbg(FYI, "Query Info\n"); | 1977 | cifs_dbg(FYI, "Query Info\n"); |
1894 | 1978 | ||
@@ -1901,6 +1985,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
1901 | if (rc) | 1985 | if (rc) |
1902 | return rc; | 1986 | return rc; |
1903 | 1987 | ||
1988 | if (encryption_required(tcon)) | ||
1989 | flags |= CIFS_TRANSFORM_REQ; | ||
1990 | |||
1904 | req->InfoType = SMB2_O_INFO_FILE; | 1991 | req->InfoType = SMB2_O_INFO_FILE; |
1905 | req->FileInfoClass = info_class; | 1992 | req->FileInfoClass = info_class; |
1906 | req->PersistentFileId = persistent_fid; | 1993 | req->PersistentFileId = persistent_fid; |
@@ -1914,8 +2001,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
1914 | /* 4 for rfc1002 length field */ | 2001 | /* 4 for rfc1002 length field */ |
1915 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 2002 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
1916 | 2003 | ||
1917 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0); | 2004 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); |
1918 | rsp = (struct smb2_query_info_rsp *)iov[0].iov_base; | 2005 | cifs_small_buf_release(req); |
2006 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; | ||
1919 | 2007 | ||
1920 | if (rc) { | 2008 | if (rc) { |
1921 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | 2009 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
@@ -1963,11 +2051,11 @@ static void | |||
1963 | smb2_echo_callback(struct mid_q_entry *mid) | 2051 | smb2_echo_callback(struct mid_q_entry *mid) |
1964 | { | 2052 | { |
1965 | struct TCP_Server_Info *server = mid->callback_data; | 2053 | struct TCP_Server_Info *server = mid->callback_data; |
1966 | struct smb2_echo_rsp *smb2 = (struct smb2_echo_rsp *)mid->resp_buf; | 2054 | struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf; |
1967 | unsigned int credits_received = 1; | 2055 | unsigned int credits_received = 1; |
1968 | 2056 | ||
1969 | if (mid->mid_state == MID_RESPONSE_RECEIVED) | 2057 | if (mid->mid_state == MID_RESPONSE_RECEIVED) |
1970 | credits_received = le16_to_cpu(smb2->hdr.CreditRequest); | 2058 | credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest); |
1971 | 2059 | ||
1972 | mutex_lock(&server->srv_mutex); | 2060 | mutex_lock(&server->srv_mutex); |
1973 | DeleteMidQEntry(mid); | 2061 | DeleteMidQEntry(mid); |
@@ -2029,9 +2117,9 @@ SMB2_echo(struct TCP_Server_Info *server) | |||
2029 | { | 2117 | { |
2030 | struct smb2_echo_req *req; | 2118 | struct smb2_echo_req *req; |
2031 | int rc = 0; | 2119 | int rc = 0; |
2032 | struct kvec iov; | 2120 | struct kvec iov[2]; |
2033 | struct smb_rqst rqst = { .rq_iov = &iov, | 2121 | struct smb_rqst rqst = { .rq_iov = iov, |
2034 | .rq_nvec = 1 }; | 2122 | .rq_nvec = 2 }; |
2035 | 2123 | ||
2036 | cifs_dbg(FYI, "In echo request\n"); | 2124 | cifs_dbg(FYI, "In echo request\n"); |
2037 | 2125 | ||
@@ -2045,14 +2133,16 @@ SMB2_echo(struct TCP_Server_Info *server) | |||
2045 | if (rc) | 2133 | if (rc) |
2046 | return rc; | 2134 | return rc; |
2047 | 2135 | ||
2048 | req->hdr.CreditRequest = cpu_to_le16(1); | 2136 | req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1); |
2049 | 2137 | ||
2050 | iov.iov_base = (char *)req; | ||
2051 | /* 4 for rfc1002 length field */ | 2138 | /* 4 for rfc1002 length field */ |
2052 | iov.iov_len = get_rfc1002_length(req) + 4; | 2139 | iov[0].iov_len = 4; |
2140 | iov[0].iov_base = (char *)req; | ||
2141 | iov[1].iov_len = get_rfc1002_length(req); | ||
2142 | iov[1].iov_base = (char *)req + 4; | ||
2053 | 2143 | ||
2054 | rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server, | 2144 | rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, |
2055 | CIFS_ECHO_OP); | 2145 | server, CIFS_ECHO_OP); |
2056 | if (rc) | 2146 | if (rc) |
2057 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); | 2147 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); |
2058 | 2148 | ||
@@ -2068,8 +2158,10 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2068 | struct TCP_Server_Info *server; | 2158 | struct TCP_Server_Info *server; |
2069 | struct cifs_ses *ses = tcon->ses; | 2159 | struct cifs_ses *ses = tcon->ses; |
2070 | struct kvec iov[1]; | 2160 | struct kvec iov[1]; |
2161 | struct kvec rsp_iov; | ||
2071 | int resp_buftype; | 2162 | int resp_buftype; |
2072 | int rc = 0; | 2163 | int rc = 0; |
2164 | int flags = 0; | ||
2073 | 2165 | ||
2074 | cifs_dbg(FYI, "Flush\n"); | 2166 | cifs_dbg(FYI, "Flush\n"); |
2075 | 2167 | ||
@@ -2082,6 +2174,9 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2082 | if (rc) | 2174 | if (rc) |
2083 | return rc; | 2175 | return rc; |
2084 | 2176 | ||
2177 | if (encryption_required(tcon)) | ||
2178 | flags |= CIFS_TRANSFORM_REQ; | ||
2179 | |||
2085 | req->PersistentFileId = persistent_fid; | 2180 | req->PersistentFileId = persistent_fid; |
2086 | req->VolatileFileId = volatile_fid; | 2181 | req->VolatileFileId = volatile_fid; |
2087 | 2182 | ||
@@ -2089,12 +2184,13 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2089 | /* 4 for rfc1002 length field */ | 2184 | /* 4 for rfc1002 length field */ |
2090 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 2185 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
2091 | 2186 | ||
2092 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0); | 2187 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); |
2188 | cifs_small_buf_release(req); | ||
2093 | 2189 | ||
2094 | if (rc != 0) | 2190 | if (rc != 0) |
2095 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); | 2191 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); |
2096 | 2192 | ||
2097 | free_rsp_buf(resp_buftype, iov[0].iov_base); | 2193 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
2098 | return rc; | 2194 | return rc; |
2099 | } | 2195 | } |
2100 | 2196 | ||
@@ -2103,19 +2199,23 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2103 | * have the end_of_chain boolean set to true. | 2199 | * have the end_of_chain boolean set to true. |
2104 | */ | 2200 | */ |
2105 | static int | 2201 | static int |
2106 | smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, | 2202 | smb2_new_read_req(void **buf, unsigned int *total_len, |
2107 | unsigned int remaining_bytes, int request_type) | 2203 | struct cifs_io_parms *io_parms, unsigned int remaining_bytes, |
2204 | int request_type) | ||
2108 | { | 2205 | { |
2109 | int rc = -EACCES; | 2206 | int rc = -EACCES; |
2110 | struct smb2_read_req *req = NULL; | 2207 | struct smb2_read_plain_req *req = NULL; |
2208 | struct smb2_sync_hdr *shdr; | ||
2111 | 2209 | ||
2112 | rc = small_smb2_init(SMB2_READ, io_parms->tcon, (void **) &req); | 2210 | rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req, |
2211 | total_len); | ||
2113 | if (rc) | 2212 | if (rc) |
2114 | return rc; | 2213 | return rc; |
2115 | if (io_parms->tcon->ses->server == NULL) | 2214 | if (io_parms->tcon->ses->server == NULL) |
2116 | return -ECONNABORTED; | 2215 | return -ECONNABORTED; |
2117 | 2216 | ||
2118 | req->hdr.ProcessId = cpu_to_le32(io_parms->pid); | 2217 | shdr = &req->sync_hdr; |
2218 | shdr->ProcessId = cpu_to_le32(io_parms->pid); | ||
2119 | 2219 | ||
2120 | req->PersistentFileId = io_parms->persistent_fid; | 2220 | req->PersistentFileId = io_parms->persistent_fid; |
2121 | req->VolatileFileId = io_parms->volatile_fid; | 2221 | req->VolatileFileId = io_parms->volatile_fid; |
@@ -2128,19 +2228,19 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, | |||
2128 | 2228 | ||
2129 | if (request_type & CHAINED_REQUEST) { | 2229 | if (request_type & CHAINED_REQUEST) { |
2130 | if (!(request_type & END_OF_CHAIN)) { | 2230 | if (!(request_type & END_OF_CHAIN)) { |
2131 | /* 4 for rfc1002 length field */ | 2231 | /* next 8-byte aligned request */ |
2132 | req->hdr.NextCommand = | 2232 | *total_len = DIV_ROUND_UP(*total_len, 8) * 8; |
2133 | cpu_to_le32(get_rfc1002_length(req) + 4); | 2233 | shdr->NextCommand = cpu_to_le32(*total_len); |
2134 | } else /* END_OF_CHAIN */ | 2234 | } else /* END_OF_CHAIN */ |
2135 | req->hdr.NextCommand = 0; | 2235 | shdr->NextCommand = 0; |
2136 | if (request_type & RELATED_REQUEST) { | 2236 | if (request_type & RELATED_REQUEST) { |
2137 | req->hdr.Flags |= SMB2_FLAGS_RELATED_OPERATIONS; | 2237 | shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS; |
2138 | /* | 2238 | /* |
2139 | * Related requests use info from previous read request | 2239 | * Related requests use info from previous read request |
2140 | * in chain. | 2240 | * in chain. |
2141 | */ | 2241 | */ |
2142 | req->hdr.SessionId = 0xFFFFFFFF; | 2242 | shdr->SessionId = 0xFFFFFFFF; |
2143 | req->hdr.TreeId = 0xFFFFFFFF; | 2243 | shdr->TreeId = 0xFFFFFFFF; |
2144 | req->PersistentFileId = 0xFFFFFFFF; | 2244 | req->PersistentFileId = 0xFFFFFFFF; |
2145 | req->VolatileFileId = 0xFFFFFFFF; | 2245 | req->VolatileFileId = 0xFFFFFFFF; |
2146 | } | 2246 | } |
@@ -2150,9 +2250,7 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, | |||
2150 | else | 2250 | else |
2151 | req->RemainingBytes = 0; | 2251 | req->RemainingBytes = 0; |
2152 | 2252 | ||
2153 | iov[0].iov_base = (char *)req; | 2253 | *buf = req; |
2154 | /* 4 for rfc1002 length field */ | ||
2155 | iov[0].iov_len = get_rfc1002_length(req) + 4; | ||
2156 | return rc; | 2254 | return rc; |
2157 | } | 2255 | } |
2158 | 2256 | ||
@@ -2162,10 +2260,11 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
2162 | struct cifs_readdata *rdata = mid->callback_data; | 2260 | struct cifs_readdata *rdata = mid->callback_data; |
2163 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | 2261 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
2164 | struct TCP_Server_Info *server = tcon->ses->server; | 2262 | struct TCP_Server_Info *server = tcon->ses->server; |
2165 | struct smb2_hdr *buf = (struct smb2_hdr *)rdata->iov.iov_base; | 2263 | struct smb2_sync_hdr *shdr = |
2264 | (struct smb2_sync_hdr *)rdata->iov[1].iov_base; | ||
2166 | unsigned int credits_received = 1; | 2265 | unsigned int credits_received = 1; |
2167 | struct smb_rqst rqst = { .rq_iov = &rdata->iov, | 2266 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
2168 | .rq_nvec = 1, | 2267 | .rq_nvec = 2, |
2169 | .rq_pages = rdata->pages, | 2268 | .rq_pages = rdata->pages, |
2170 | .rq_npages = rdata->nr_pages, | 2269 | .rq_npages = rdata->nr_pages, |
2171 | .rq_pagesz = rdata->pagesz, | 2270 | .rq_pagesz = rdata->pagesz, |
@@ -2177,9 +2276,9 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
2177 | 2276 | ||
2178 | switch (mid->mid_state) { | 2277 | switch (mid->mid_state) { |
2179 | case MID_RESPONSE_RECEIVED: | 2278 | case MID_RESPONSE_RECEIVED: |
2180 | credits_received = le16_to_cpu(buf->CreditRequest); | 2279 | credits_received = le16_to_cpu(shdr->CreditRequest); |
2181 | /* result already set, check signature */ | 2280 | /* result already set, check signature */ |
2182 | if (server->sign) { | 2281 | if (server->sign && !mid->decrypted) { |
2183 | int rc; | 2282 | int rc; |
2184 | 2283 | ||
2185 | rc = smb2_verify_signature(&rqst, server); | 2284 | rc = smb2_verify_signature(&rqst, server); |
@@ -2216,16 +2315,19 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
2216 | add_credits(server, credits_received, 0); | 2315 | add_credits(server, credits_received, 0); |
2217 | } | 2316 | } |
2218 | 2317 | ||
2219 | /* smb2_async_readv - send an async write, and set up mid to handle result */ | 2318 | /* smb2_async_readv - send an async read, and set up mid to handle result */ |
2220 | int | 2319 | int |
2221 | smb2_async_readv(struct cifs_readdata *rdata) | 2320 | smb2_async_readv(struct cifs_readdata *rdata) |
2222 | { | 2321 | { |
2223 | int rc, flags = 0; | 2322 | int rc, flags = 0; |
2224 | struct smb2_hdr *buf; | 2323 | char *buf; |
2324 | struct smb2_sync_hdr *shdr; | ||
2225 | struct cifs_io_parms io_parms; | 2325 | struct cifs_io_parms io_parms; |
2226 | struct smb_rqst rqst = { .rq_iov = &rdata->iov, | 2326 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
2227 | .rq_nvec = 1 }; | 2327 | .rq_nvec = 2 }; |
2228 | struct TCP_Server_Info *server; | 2328 | struct TCP_Server_Info *server; |
2329 | unsigned int total_len; | ||
2330 | __be32 req_len; | ||
2229 | 2331 | ||
2230 | cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", | 2332 | cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", |
2231 | __func__, rdata->offset, rdata->bytes); | 2333 | __func__, rdata->offset, rdata->bytes); |
@@ -2239,7 +2341,7 @@ smb2_async_readv(struct cifs_readdata *rdata) | |||
2239 | 2341 | ||
2240 | server = io_parms.tcon->ses->server; | 2342 | server = io_parms.tcon->ses->server; |
2241 | 2343 | ||
2242 | rc = smb2_new_read_req(&rdata->iov, &io_parms, 0, 0); | 2344 | rc = smb2_new_read_req((void **) &buf, &total_len, &io_parms, 0, 0); |
2243 | if (rc) { | 2345 | if (rc) { |
2244 | if (rc == -EAGAIN && rdata->credits) { | 2346 | if (rc == -EAGAIN && rdata->credits) { |
2245 | /* credits was reset by reconnect */ | 2347 | /* credits was reset by reconnect */ |
@@ -2252,26 +2354,34 @@ smb2_async_readv(struct cifs_readdata *rdata) | |||
2252 | return rc; | 2354 | return rc; |
2253 | } | 2355 | } |
2254 | 2356 | ||
2255 | buf = (struct smb2_hdr *)rdata->iov.iov_base; | 2357 | if (encryption_required(io_parms.tcon)) |
2256 | /* 4 for rfc1002 length field */ | 2358 | flags |= CIFS_TRANSFORM_REQ; |
2257 | rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4; | 2359 | |
2360 | req_len = cpu_to_be32(total_len); | ||
2361 | |||
2362 | rdata->iov[0].iov_base = &req_len; | ||
2363 | rdata->iov[0].iov_len = sizeof(__be32); | ||
2364 | rdata->iov[1].iov_base = buf; | ||
2365 | rdata->iov[1].iov_len = total_len; | ||
2366 | |||
2367 | shdr = (struct smb2_sync_hdr *)buf; | ||
2258 | 2368 | ||
2259 | if (rdata->credits) { | 2369 | if (rdata->credits) { |
2260 | buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, | 2370 | shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, |
2261 | SMB2_MAX_BUFFER_SIZE)); | 2371 | SMB2_MAX_BUFFER_SIZE)); |
2262 | buf->CreditRequest = buf->CreditCharge; | 2372 | shdr->CreditRequest = shdr->CreditCharge; |
2263 | spin_lock(&server->req_lock); | 2373 | spin_lock(&server->req_lock); |
2264 | server->credits += rdata->credits - | 2374 | server->credits += rdata->credits - |
2265 | le16_to_cpu(buf->CreditCharge); | 2375 | le16_to_cpu(shdr->CreditCharge); |
2266 | spin_unlock(&server->req_lock); | 2376 | spin_unlock(&server->req_lock); |
2267 | wake_up(&server->request_q); | 2377 | wake_up(&server->request_q); |
2268 | flags = CIFS_HAS_CREDITS; | 2378 | flags |= CIFS_HAS_CREDITS; |
2269 | } | 2379 | } |
2270 | 2380 | ||
2271 | kref_get(&rdata->refcount); | 2381 | kref_get(&rdata->refcount); |
2272 | rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, | 2382 | rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, |
2273 | cifs_readv_receive, smb2_readv_callback, | 2383 | cifs_readv_receive, smb2_readv_callback, |
2274 | rdata, flags); | 2384 | smb3_handle_read_data, rdata, flags); |
2275 | if (rc) { | 2385 | if (rc) { |
2276 | kref_put(&rdata->refcount, cifs_readdata_release); | 2386 | kref_put(&rdata->refcount, cifs_readdata_release); |
2277 | cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); | 2387 | cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); |
@@ -2286,21 +2396,41 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2286 | unsigned int *nbytes, char **buf, int *buf_type) | 2396 | unsigned int *nbytes, char **buf, int *buf_type) |
2287 | { | 2397 | { |
2288 | int resp_buftype, rc = -EACCES; | 2398 | int resp_buftype, rc = -EACCES; |
2399 | struct smb2_read_plain_req *req = NULL; | ||
2289 | struct smb2_read_rsp *rsp = NULL; | 2400 | struct smb2_read_rsp *rsp = NULL; |
2290 | struct kvec iov[1]; | 2401 | struct smb2_sync_hdr *shdr; |
2402 | struct kvec iov[2]; | ||
2403 | struct kvec rsp_iov; | ||
2404 | unsigned int total_len; | ||
2405 | __be32 req_len; | ||
2406 | struct smb_rqst rqst = { .rq_iov = iov, | ||
2407 | .rq_nvec = 2 }; | ||
2408 | int flags = CIFS_LOG_ERROR; | ||
2409 | struct cifs_ses *ses = io_parms->tcon->ses; | ||
2291 | 2410 | ||
2292 | *nbytes = 0; | 2411 | *nbytes = 0; |
2293 | rc = smb2_new_read_req(iov, io_parms, 0, 0); | 2412 | rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0); |
2294 | if (rc) | 2413 | if (rc) |
2295 | return rc; | 2414 | return rc; |
2296 | 2415 | ||
2297 | rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1, | 2416 | if (encryption_required(io_parms->tcon)) |
2298 | &resp_buftype, CIFS_LOG_ERROR); | 2417 | flags |= CIFS_TRANSFORM_REQ; |
2299 | 2418 | ||
2300 | rsp = (struct smb2_read_rsp *)iov[0].iov_base; | 2419 | req_len = cpu_to_be32(total_len); |
2301 | 2420 | ||
2302 | if (rsp->hdr.Status == STATUS_END_OF_FILE) { | 2421 | iov[0].iov_base = &req_len; |
2303 | free_rsp_buf(resp_buftype, iov[0].iov_base); | 2422 | iov[0].iov_len = sizeof(__be32); |
2423 | iov[1].iov_base = req; | ||
2424 | iov[1].iov_len = total_len; | ||
2425 | |||
2426 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); | ||
2427 | cifs_small_buf_release(req); | ||
2428 | |||
2429 | rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; | ||
2430 | shdr = get_sync_hdr(rsp); | ||
2431 | |||
2432 | if (shdr->Status == STATUS_END_OF_FILE) { | ||
2433 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | ||
2304 | return 0; | 2434 | return 0; |
2305 | } | 2435 | } |
2306 | 2436 | ||
@@ -2319,11 +2449,10 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2319 | } | 2449 | } |
2320 | 2450 | ||
2321 | if (*buf) { | 2451 | if (*buf) { |
2322 | memcpy(*buf, (char *)&rsp->hdr.ProtocolId + rsp->DataOffset, | 2452 | memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes); |
2323 | *nbytes); | 2453 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
2324 | free_rsp_buf(resp_buftype, iov[0].iov_base); | ||
2325 | } else if (resp_buftype != CIFS_NO_BUFFER) { | 2454 | } else if (resp_buftype != CIFS_NO_BUFFER) { |
2326 | *buf = iov[0].iov_base; | 2455 | *buf = rsp_iov.iov_base; |
2327 | if (resp_buftype == CIFS_SMALL_BUFFER) | 2456 | if (resp_buftype == CIFS_SMALL_BUFFER) |
2328 | *buf_type = CIFS_SMALL_BUFFER; | 2457 | *buf_type = CIFS_SMALL_BUFFER; |
2329 | else if (resp_buftype == CIFS_LARGE_BUFFER) | 2458 | else if (resp_buftype == CIFS_LARGE_BUFFER) |
@@ -2348,7 +2477,7 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
2348 | 2477 | ||
2349 | switch (mid->mid_state) { | 2478 | switch (mid->mid_state) { |
2350 | case MID_RESPONSE_RECEIVED: | 2479 | case MID_RESPONSE_RECEIVED: |
2351 | credits_received = le16_to_cpu(rsp->hdr.CreditRequest); | 2480 | credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest); |
2352 | wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); | 2481 | wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); |
2353 | if (wdata->result != 0) | 2482 | if (wdata->result != 0) |
2354 | break; | 2483 | break; |
@@ -2394,10 +2523,11 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
2394 | { | 2523 | { |
2395 | int rc = -EACCES, flags = 0; | 2524 | int rc = -EACCES, flags = 0; |
2396 | struct smb2_write_req *req = NULL; | 2525 | struct smb2_write_req *req = NULL; |
2526 | struct smb2_sync_hdr *shdr; | ||
2397 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | 2527 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
2398 | struct TCP_Server_Info *server = tcon->ses->server; | 2528 | struct TCP_Server_Info *server = tcon->ses->server; |
2399 | struct kvec iov; | 2529 | struct kvec iov[2]; |
2400 | struct smb_rqst rqst; | 2530 | struct smb_rqst rqst = { }; |
2401 | 2531 | ||
2402 | rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); | 2532 | rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); |
2403 | if (rc) { | 2533 | if (rc) { |
@@ -2412,7 +2542,11 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
2412 | goto async_writev_out; | 2542 | goto async_writev_out; |
2413 | } | 2543 | } |
2414 | 2544 | ||
2415 | req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid); | 2545 | if (encryption_required(tcon)) |
2546 | flags |= CIFS_TRANSFORM_REQ; | ||
2547 | |||
2548 | shdr = get_sync_hdr(req); | ||
2549 | shdr->ProcessId = cpu_to_le32(wdata->cfile->pid); | ||
2416 | 2550 | ||
2417 | req->PersistentFileId = wdata->cfile->fid.persistent_fid; | 2551 | req->PersistentFileId = wdata->cfile->fid.persistent_fid; |
2418 | req->VolatileFileId = wdata->cfile->fid.volatile_fid; | 2552 | req->VolatileFileId = wdata->cfile->fid.volatile_fid; |
@@ -2426,11 +2560,13 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
2426 | req->RemainingBytes = 0; | 2560 | req->RemainingBytes = 0; |
2427 | 2561 | ||
2428 | /* 4 for rfc1002 length field and 1 for Buffer */ | 2562 | /* 4 for rfc1002 length field and 1 for Buffer */ |
2429 | iov.iov_len = get_rfc1002_length(req) + 4 - 1; | 2563 | iov[0].iov_len = 4; |
2430 | iov.iov_base = req; | 2564 | iov[0].iov_base = req; |
2565 | iov[1].iov_len = get_rfc1002_length(req) - 1; | ||
2566 | iov[1].iov_base = (char *)req + 4; | ||
2431 | 2567 | ||
2432 | rqst.rq_iov = &iov; | 2568 | rqst.rq_iov = iov; |
2433 | rqst.rq_nvec = 1; | 2569 | rqst.rq_nvec = 2; |
2434 | rqst.rq_pages = wdata->pages; | 2570 | rqst.rq_pages = wdata->pages; |
2435 | rqst.rq_npages = wdata->nr_pages; | 2571 | rqst.rq_npages = wdata->nr_pages; |
2436 | rqst.rq_pagesz = wdata->pagesz; | 2572 | rqst.rq_pagesz = wdata->pagesz; |
@@ -2444,20 +2580,20 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
2444 | inc_rfc1001_len(&req->hdr, wdata->bytes - 1 /* Buffer */); | 2580 | inc_rfc1001_len(&req->hdr, wdata->bytes - 1 /* Buffer */); |
2445 | 2581 | ||
2446 | if (wdata->credits) { | 2582 | if (wdata->credits) { |
2447 | req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, | 2583 | shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, |
2448 | SMB2_MAX_BUFFER_SIZE)); | 2584 | SMB2_MAX_BUFFER_SIZE)); |
2449 | req->hdr.CreditRequest = req->hdr.CreditCharge; | 2585 | shdr->CreditRequest = shdr->CreditCharge; |
2450 | spin_lock(&server->req_lock); | 2586 | spin_lock(&server->req_lock); |
2451 | server->credits += wdata->credits - | 2587 | server->credits += wdata->credits - |
2452 | le16_to_cpu(req->hdr.CreditCharge); | 2588 | le16_to_cpu(shdr->CreditCharge); |
2453 | spin_unlock(&server->req_lock); | 2589 | spin_unlock(&server->req_lock); |
2454 | wake_up(&server->request_q); | 2590 | wake_up(&server->request_q); |
2455 | flags = CIFS_HAS_CREDITS; | 2591 | flags |= CIFS_HAS_CREDITS; |
2456 | } | 2592 | } |
2457 | 2593 | ||
2458 | kref_get(&wdata->refcount); | 2594 | kref_get(&wdata->refcount); |
2459 | rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, wdata, | 2595 | rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, |
2460 | flags); | 2596 | wdata, flags); |
2461 | 2597 | ||
2462 | if (rc) { | 2598 | if (rc) { |
2463 | kref_put(&wdata->refcount, release); | 2599 | kref_put(&wdata->refcount, release); |
@@ -2483,6 +2619,9 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2483 | struct smb2_write_req *req = NULL; | 2619 | struct smb2_write_req *req = NULL; |
2484 | struct smb2_write_rsp *rsp = NULL; | 2620 | struct smb2_write_rsp *rsp = NULL; |
2485 | int resp_buftype; | 2621 | int resp_buftype; |
2622 | struct kvec rsp_iov; | ||
2623 | int flags = 0; | ||
2624 | |||
2486 | *nbytes = 0; | 2625 | *nbytes = 0; |
2487 | 2626 | ||
2488 | if (n_vec < 1) | 2627 | if (n_vec < 1) |
@@ -2495,7 +2634,10 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2495 | if (io_parms->tcon->ses->server == NULL) | 2634 | if (io_parms->tcon->ses->server == NULL) |
2496 | return -ECONNABORTED; | 2635 | return -ECONNABORTED; |
2497 | 2636 | ||
2498 | req->hdr.ProcessId = cpu_to_le32(io_parms->pid); | 2637 | if (encryption_required(io_parms->tcon)) |
2638 | flags |= CIFS_TRANSFORM_REQ; | ||
2639 | |||
2640 | req->hdr.sync_hdr.ProcessId = cpu_to_le32(io_parms->pid); | ||
2499 | 2641 | ||
2500 | req->PersistentFileId = io_parms->persistent_fid; | 2642 | req->PersistentFileId = io_parms->persistent_fid; |
2501 | req->VolatileFileId = io_parms->volatile_fid; | 2643 | req->VolatileFileId = io_parms->volatile_fid; |
@@ -2517,8 +2659,9 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2517 | inc_rfc1001_len(req, io_parms->length - 1 /* Buffer */); | 2659 | inc_rfc1001_len(req, io_parms->length - 1 /* Buffer */); |
2518 | 2660 | ||
2519 | rc = SendReceive2(xid, io_parms->tcon->ses, iov, n_vec + 1, | 2661 | rc = SendReceive2(xid, io_parms->tcon->ses, iov, n_vec + 1, |
2520 | &resp_buftype, 0); | 2662 | &resp_buftype, flags, &rsp_iov); |
2521 | rsp = (struct smb2_write_rsp *)iov[0].iov_base; | 2663 | cifs_small_buf_release(req); |
2664 | rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; | ||
2522 | 2665 | ||
2523 | if (rc) { | 2666 | if (rc) { |
2524 | cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); | 2667 | cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); |
@@ -2581,6 +2724,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
2581 | struct smb2_query_directory_req *req; | 2724 | struct smb2_query_directory_req *req; |
2582 | struct smb2_query_directory_rsp *rsp = NULL; | 2725 | struct smb2_query_directory_rsp *rsp = NULL; |
2583 | struct kvec iov[2]; | 2726 | struct kvec iov[2]; |
2727 | struct kvec rsp_iov; | ||
2584 | int rc = 0; | 2728 | int rc = 0; |
2585 | int len; | 2729 | int len; |
2586 | int resp_buftype = CIFS_NO_BUFFER; | 2730 | int resp_buftype = CIFS_NO_BUFFER; |
@@ -2591,6 +2735,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
2591 | char *end_of_smb; | 2735 | char *end_of_smb; |
2592 | unsigned int output_size = CIFSMaxBufSize; | 2736 | unsigned int output_size = CIFSMaxBufSize; |
2593 | size_t info_buf_size; | 2737 | size_t info_buf_size; |
2738 | int flags = 0; | ||
2594 | 2739 | ||
2595 | if (ses && (ses->server)) | 2740 | if (ses && (ses->server)) |
2596 | server = ses->server; | 2741 | server = ses->server; |
@@ -2601,6 +2746,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
2601 | if (rc) | 2746 | if (rc) |
2602 | return rc; | 2747 | return rc; |
2603 | 2748 | ||
2749 | if (encryption_required(tcon)) | ||
2750 | flags |= CIFS_TRANSFORM_REQ; | ||
2751 | |||
2604 | switch (srch_inf->info_level) { | 2752 | switch (srch_inf->info_level) { |
2605 | case SMB_FIND_FILE_DIRECTORY_INFO: | 2753 | case SMB_FIND_FILE_DIRECTORY_INFO: |
2606 | req->FileInformationClass = FILE_DIRECTORY_INFORMATION; | 2754 | req->FileInformationClass = FILE_DIRECTORY_INFORMATION; |
@@ -2645,11 +2793,13 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
2645 | 2793 | ||
2646 | inc_rfc1001_len(req, len - 1 /* Buffer */); | 2794 | inc_rfc1001_len(req, len - 1 /* Buffer */); |
2647 | 2795 | ||
2648 | rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0); | 2796 | rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov); |
2649 | rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; | 2797 | cifs_small_buf_release(req); |
2798 | rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; | ||
2650 | 2799 | ||
2651 | if (rc) { | 2800 | if (rc) { |
2652 | if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) { | 2801 | if (rc == -ENODATA && |
2802 | rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) { | ||
2653 | srch_inf->endOfSearch = true; | 2803 | srch_inf->endOfSearch = true; |
2654 | rc = 0; | 2804 | rc = 0; |
2655 | } | 2805 | } |
@@ -2705,11 +2855,13 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2705 | struct smb2_set_info_req *req; | 2855 | struct smb2_set_info_req *req; |
2706 | struct smb2_set_info_rsp *rsp = NULL; | 2856 | struct smb2_set_info_rsp *rsp = NULL; |
2707 | struct kvec *iov; | 2857 | struct kvec *iov; |
2858 | struct kvec rsp_iov; | ||
2708 | int rc = 0; | 2859 | int rc = 0; |
2709 | int resp_buftype; | 2860 | int resp_buftype; |
2710 | unsigned int i; | 2861 | unsigned int i; |
2711 | struct TCP_Server_Info *server; | 2862 | struct TCP_Server_Info *server; |
2712 | struct cifs_ses *ses = tcon->ses; | 2863 | struct cifs_ses *ses = tcon->ses; |
2864 | int flags = 0; | ||
2713 | 2865 | ||
2714 | if (ses && (ses->server)) | 2866 | if (ses && (ses->server)) |
2715 | server = ses->server; | 2867 | server = ses->server; |
@@ -2729,7 +2881,10 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2729 | return rc; | 2881 | return rc; |
2730 | } | 2882 | } |
2731 | 2883 | ||
2732 | req->hdr.ProcessId = cpu_to_le32(pid); | 2884 | if (encryption_required(tcon)) |
2885 | flags |= CIFS_TRANSFORM_REQ; | ||
2886 | |||
2887 | req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid); | ||
2733 | 2888 | ||
2734 | req->InfoType = SMB2_O_INFO_FILE; | 2889 | req->InfoType = SMB2_O_INFO_FILE; |
2735 | req->FileInfoClass = info_class; | 2890 | req->FileInfoClass = info_class; |
@@ -2756,8 +2911,9 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2756 | iov[i].iov_len = size[i]; | 2911 | iov[i].iov_len = size[i]; |
2757 | } | 2912 | } |
2758 | 2913 | ||
2759 | rc = SendReceive2(xid, ses, iov, num, &resp_buftype, 0); | 2914 | rc = SendReceive2(xid, ses, iov, num, &resp_buftype, flags, &rsp_iov); |
2760 | rsp = (struct smb2_set_info_rsp *)iov[0].iov_base; | 2915 | cifs_small_buf_release(req); |
2916 | rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; | ||
2761 | 2917 | ||
2762 | if (rc != 0) | 2918 | if (rc != 0) |
2763 | cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); | 2919 | cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); |
@@ -2885,20 +3041,23 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
2885 | { | 3041 | { |
2886 | int rc; | 3042 | int rc; |
2887 | struct smb2_oplock_break *req = NULL; | 3043 | struct smb2_oplock_break *req = NULL; |
3044 | int flags = CIFS_OBREAK_OP; | ||
2888 | 3045 | ||
2889 | cifs_dbg(FYI, "SMB2_oplock_break\n"); | 3046 | cifs_dbg(FYI, "SMB2_oplock_break\n"); |
2890 | rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req); | 3047 | rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req); |
2891 | |||
2892 | if (rc) | 3048 | if (rc) |
2893 | return rc; | 3049 | return rc; |
2894 | 3050 | ||
3051 | if (encryption_required(tcon)) | ||
3052 | flags |= CIFS_TRANSFORM_REQ; | ||
3053 | |||
2895 | req->VolatileFid = volatile_fid; | 3054 | req->VolatileFid = volatile_fid; |
2896 | req->PersistentFid = persistent_fid; | 3055 | req->PersistentFid = persistent_fid; |
2897 | req->OplockLevel = oplock_level; | 3056 | req->OplockLevel = oplock_level; |
2898 | req->hdr.CreditRequest = cpu_to_le16(1); | 3057 | req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1); |
2899 | 3058 | ||
2900 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, CIFS_OBREAK_OP); | 3059 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, flags); |
2901 | /* SMB2 buffer freed by function above */ | 3060 | cifs_small_buf_release(req); |
2902 | 3061 | ||
2903 | if (rc) { | 3062 | if (rc) { |
2904 | cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); | 3063 | cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); |
@@ -2958,10 +3117,12 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2958 | { | 3117 | { |
2959 | struct smb2_query_info_rsp *rsp = NULL; | 3118 | struct smb2_query_info_rsp *rsp = NULL; |
2960 | struct kvec iov; | 3119 | struct kvec iov; |
3120 | struct kvec rsp_iov; | ||
2961 | int rc = 0; | 3121 | int rc = 0; |
2962 | int resp_buftype; | 3122 | int resp_buftype; |
2963 | struct cifs_ses *ses = tcon->ses; | 3123 | struct cifs_ses *ses = tcon->ses; |
2964 | struct smb2_fs_full_size_info *info = NULL; | 3124 | struct smb2_fs_full_size_info *info = NULL; |
3125 | int flags = 0; | ||
2965 | 3126 | ||
2966 | rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION, | 3127 | rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION, |
2967 | sizeof(struct smb2_fs_full_size_info), | 3128 | sizeof(struct smb2_fs_full_size_info), |
@@ -2969,12 +3130,16 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2969 | if (rc) | 3130 | if (rc) |
2970 | return rc; | 3131 | return rc; |
2971 | 3132 | ||
2972 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); | 3133 | if (encryption_required(tcon)) |
3134 | flags |= CIFS_TRANSFORM_REQ; | ||
3135 | |||
3136 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); | ||
3137 | cifs_small_buf_release(iov.iov_base); | ||
2973 | if (rc) { | 3138 | if (rc) { |
2974 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | 3139 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
2975 | goto qfsinf_exit; | 3140 | goto qfsinf_exit; |
2976 | } | 3141 | } |
2977 | rsp = (struct smb2_query_info_rsp *)iov.iov_base; | 3142 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
2978 | 3143 | ||
2979 | info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ + | 3144 | info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ + |
2980 | le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr); | 3145 | le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr); |
@@ -2985,7 +3150,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2985 | copy_fs_info_to_kstatfs(info, fsdata); | 3150 | copy_fs_info_to_kstatfs(info, fsdata); |
2986 | 3151 | ||
2987 | qfsinf_exit: | 3152 | qfsinf_exit: |
2988 | free_rsp_buf(resp_buftype, iov.iov_base); | 3153 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
2989 | return rc; | 3154 | return rc; |
2990 | } | 3155 | } |
2991 | 3156 | ||
@@ -2995,10 +3160,12 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
2995 | { | 3160 | { |
2996 | struct smb2_query_info_rsp *rsp = NULL; | 3161 | struct smb2_query_info_rsp *rsp = NULL; |
2997 | struct kvec iov; | 3162 | struct kvec iov; |
3163 | struct kvec rsp_iov; | ||
2998 | int rc = 0; | 3164 | int rc = 0; |
2999 | int resp_buftype, max_len, min_len; | 3165 | int resp_buftype, max_len, min_len; |
3000 | struct cifs_ses *ses = tcon->ses; | 3166 | struct cifs_ses *ses = tcon->ses; |
3001 | unsigned int rsp_len, offset; | 3167 | unsigned int rsp_len, offset; |
3168 | int flags = 0; | ||
3002 | 3169 | ||
3003 | if (level == FS_DEVICE_INFORMATION) { | 3170 | if (level == FS_DEVICE_INFORMATION) { |
3004 | max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); | 3171 | max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); |
@@ -3019,12 +3186,16 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
3019 | if (rc) | 3186 | if (rc) |
3020 | return rc; | 3187 | return rc; |
3021 | 3188 | ||
3022 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); | 3189 | if (encryption_required(tcon)) |
3190 | flags |= CIFS_TRANSFORM_REQ; | ||
3191 | |||
3192 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); | ||
3193 | cifs_small_buf_release(iov.iov_base); | ||
3023 | if (rc) { | 3194 | if (rc) { |
3024 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | 3195 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
3025 | goto qfsattr_exit; | 3196 | goto qfsattr_exit; |
3026 | } | 3197 | } |
3027 | rsp = (struct smb2_query_info_rsp *)iov.iov_base; | 3198 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
3028 | 3199 | ||
3029 | rsp_len = le32_to_cpu(rsp->OutputBufferLength); | 3200 | rsp_len = le32_to_cpu(rsp->OutputBufferLength); |
3030 | offset = le16_to_cpu(rsp->OutputBufferOffset); | 3201 | offset = le16_to_cpu(rsp->OutputBufferOffset); |
@@ -3048,7 +3219,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
3048 | } | 3219 | } |
3049 | 3220 | ||
3050 | qfsattr_exit: | 3221 | qfsattr_exit: |
3051 | free_rsp_buf(resp_buftype, iov.iov_base); | 3222 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
3052 | return rc; | 3223 | return rc; |
3053 | } | 3224 | } |
3054 | 3225 | ||
@@ -3060,8 +3231,10 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
3060 | int rc = 0; | 3231 | int rc = 0; |
3061 | struct smb2_lock_req *req = NULL; | 3232 | struct smb2_lock_req *req = NULL; |
3062 | struct kvec iov[2]; | 3233 | struct kvec iov[2]; |
3234 | struct kvec rsp_iov; | ||
3063 | int resp_buf_type; | 3235 | int resp_buf_type; |
3064 | unsigned int count; | 3236 | unsigned int count; |
3237 | int flags = CIFS_NO_RESP; | ||
3065 | 3238 | ||
3066 | cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); | 3239 | cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); |
3067 | 3240 | ||
@@ -3069,7 +3242,10 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
3069 | if (rc) | 3242 | if (rc) |
3070 | return rc; | 3243 | return rc; |
3071 | 3244 | ||
3072 | req->hdr.ProcessId = cpu_to_le32(pid); | 3245 | if (encryption_required(tcon)) |
3246 | flags |= CIFS_TRANSFORM_REQ; | ||
3247 | |||
3248 | req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid); | ||
3073 | req->LockCount = cpu_to_le16(num_lock); | 3249 | req->LockCount = cpu_to_le16(num_lock); |
3074 | 3250 | ||
3075 | req->PersistentFileId = persist_fid; | 3251 | req->PersistentFileId = persist_fid; |
@@ -3085,7 +3261,9 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
3085 | iov[1].iov_len = count; | 3261 | iov[1].iov_len = count; |
3086 | 3262 | ||
3087 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); | 3263 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); |
3088 | rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP); | 3264 | rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, flags, |
3265 | &rsp_iov); | ||
3266 | cifs_small_buf_release(req); | ||
3089 | if (rc) { | 3267 | if (rc) { |
3090 | cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc); | 3268 | cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc); |
3091 | cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); | 3269 | cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); |
@@ -3117,22 +3295,25 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
3117 | { | 3295 | { |
3118 | int rc; | 3296 | int rc; |
3119 | struct smb2_lease_ack *req = NULL; | 3297 | struct smb2_lease_ack *req = NULL; |
3298 | int flags = CIFS_OBREAK_OP; | ||
3120 | 3299 | ||
3121 | cifs_dbg(FYI, "SMB2_lease_break\n"); | 3300 | cifs_dbg(FYI, "SMB2_lease_break\n"); |
3122 | rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req); | 3301 | rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req); |
3123 | |||
3124 | if (rc) | 3302 | if (rc) |
3125 | return rc; | 3303 | return rc; |
3126 | 3304 | ||
3127 | req->hdr.CreditRequest = cpu_to_le16(1); | 3305 | if (encryption_required(tcon)) |
3306 | flags |= CIFS_TRANSFORM_REQ; | ||
3307 | |||
3308 | req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1); | ||
3128 | req->StructureSize = cpu_to_le16(36); | 3309 | req->StructureSize = cpu_to_le16(36); |
3129 | inc_rfc1001_len(req, 12); | 3310 | inc_rfc1001_len(req, 12); |
3130 | 3311 | ||
3131 | memcpy(req->LeaseKey, lease_key, 16); | 3312 | memcpy(req->LeaseKey, lease_key, 16); |
3132 | req->LeaseState = lease_state; | 3313 | req->LeaseState = lease_state; |
3133 | 3314 | ||
3134 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, CIFS_OBREAK_OP); | 3315 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, flags); |
3135 | /* SMB2 buffer freed by function above */ | 3316 | cifs_small_buf_release(req); |
3136 | 3317 | ||
3137 | if (rc) { | 3318 | if (rc) { |
3138 | cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); | 3319 | cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index dc0d141f33e2..c03b252501a1 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -101,10 +101,7 @@ | |||
101 | 101 | ||
102 | #define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64) | 102 | #define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64) |
103 | 103 | ||
104 | struct smb2_hdr { | 104 | struct smb2_sync_hdr { |
105 | __be32 smb2_buf_length; /* big endian on wire */ | ||
106 | /* length is only two or three bytes - with | ||
107 | one or two byte type preceding it that MBZ */ | ||
108 | __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ | 105 | __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ |
109 | __le16 StructureSize; /* 64 */ | 106 | __le16 StructureSize; /* 64 */ |
110 | __le16 CreditCharge; /* MBZ */ | 107 | __le16 CreditCharge; /* MBZ */ |
@@ -120,16 +117,31 @@ struct smb2_hdr { | |||
120 | __u8 Signature[16]; | 117 | __u8 Signature[16]; |
121 | } __packed; | 118 | } __packed; |
122 | 119 | ||
120 | struct smb2_sync_pdu { | ||
121 | struct smb2_sync_hdr sync_hdr; | ||
122 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ | ||
123 | } __packed; | ||
124 | |||
125 | struct smb2_hdr { | ||
126 | __be32 smb2_buf_length; /* big endian on wire */ | ||
127 | /* length is only two or three bytes - with */ | ||
128 | /* one or two byte type preceding it that MBZ */ | ||
129 | struct smb2_sync_hdr sync_hdr; | ||
130 | } __packed; | ||
131 | |||
123 | struct smb2_pdu { | 132 | struct smb2_pdu { |
124 | struct smb2_hdr hdr; | 133 | struct smb2_hdr hdr; |
125 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ | 134 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ |
126 | } __packed; | 135 | } __packed; |
127 | 136 | ||
137 | #define SMB3_AES128CMM_NONCE 11 | ||
138 | #define SMB3_AES128GCM_NONCE 12 | ||
139 | |||
128 | struct smb2_transform_hdr { | 140 | struct smb2_transform_hdr { |
129 | __be32 smb2_buf_length; /* big endian on wire */ | 141 | __be32 smb2_buf_length; /* big endian on wire */ |
130 | /* length is only two or three bytes - with | 142 | /* length is only two or three bytes - with |
131 | one or two byte type preceding it that MBZ */ | 143 | one or two byte type preceding it that MBZ */ |
132 | __u8 ProtocolId[4]; /* 0xFD 'S' 'M' 'B' */ | 144 | __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ |
133 | __u8 Signature[16]; | 145 | __u8 Signature[16]; |
134 | __u8 Nonce[16]; | 146 | __u8 Nonce[16]; |
135 | __le32 OriginalMessageSize; | 147 | __le32 OriginalMessageSize; |
@@ -814,8 +826,9 @@ struct smb2_flush_rsp { | |||
814 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ | 826 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ |
815 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ | 827 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ |
816 | 828 | ||
817 | struct smb2_read_req { | 829 | /* SMB2 read request without RFC1001 length at the beginning */ |
818 | struct smb2_hdr hdr; | 830 | struct smb2_read_plain_req { |
831 | struct smb2_sync_hdr sync_hdr; | ||
819 | __le16 StructureSize; /* Must be 49 */ | 832 | __le16 StructureSize; /* Must be 49 */ |
820 | __u8 Padding; /* offset from start of SMB2 header to place read */ | 833 | __u8 Padding; /* offset from start of SMB2 header to place read */ |
821 | __u8 Flags; /* MBZ unless SMB3.02 or later */ | 834 | __u8 Flags; /* MBZ unless SMB3.02 or later */ |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index f2d511a6971b..85fc7a789334 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -56,6 +56,10 @@ extern void smb2_echo_request(struct work_struct *work); | |||
56 | extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); | 56 | extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); |
57 | extern bool smb2_is_valid_oplock_break(char *buffer, | 57 | extern bool smb2_is_valid_oplock_break(char *buffer, |
58 | struct TCP_Server_Info *srv); | 58 | struct TCP_Server_Info *srv); |
59 | extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, | ||
60 | __u64 ses_id); | ||
61 | extern int smb3_handle_read_data(struct TCP_Server_Info *server, | ||
62 | struct mid_q_entry *mid); | ||
59 | 63 | ||
60 | extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, | 64 | extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, |
61 | struct smb2_file_all_info *src); | 65 | struct smb2_file_all_info *src); |
@@ -97,6 +101,7 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile, | |||
97 | struct file_lock *flock, const unsigned int xid); | 101 | struct file_lock *flock, const unsigned int xid); |
98 | extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); | 102 | extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); |
99 | extern void smb2_reconnect_server(struct work_struct *work); | 103 | extern void smb2_reconnect_server(struct work_struct *work); |
104 | extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); | ||
100 | 105 | ||
101 | /* | 106 | /* |
102 | * SMB2 Worker functions - most of protocol specific implementation details | 107 | * SMB2 Worker functions - most of protocol specific implementation details |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index bc9a7b634643..7c3bb1bd7eed 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
32 | #include <linux/mempool.h> | 32 | #include <linux/mempool.h> |
33 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
34 | #include <crypto/aead.h> | ||
34 | #include "smb2pdu.h" | 35 | #include "smb2pdu.h" |
35 | #include "cifsglob.h" | 36 | #include "cifsglob.h" |
36 | #include "cifsproto.h" | 37 | #include "cifsproto.h" |
@@ -114,14 +115,14 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
114 | return 0; | 115 | return 0; |
115 | } | 116 | } |
116 | 117 | ||
117 | static struct cifs_ses * | 118 | struct cifs_ses * |
118 | smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) | 119 | smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id) |
119 | { | 120 | { |
120 | struct cifs_ses *ses; | 121 | struct cifs_ses *ses; |
121 | 122 | ||
122 | spin_lock(&cifs_tcp_ses_lock); | 123 | spin_lock(&cifs_tcp_ses_lock); |
123 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | 124 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
124 | if (ses->Suid != smb2hdr->SessionId) | 125 | if (ses->Suid != ses_id) |
125 | continue; | 126 | continue; |
126 | spin_unlock(&cifs_tcp_ses_lock); | 127 | spin_unlock(&cifs_tcp_ses_lock); |
127 | return ses; | 128 | return ses; |
@@ -131,7 +132,6 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) | |||
131 | return NULL; | 132 | return NULL; |
132 | } | 133 | } |
133 | 134 | ||
134 | |||
135 | int | 135 | int |
136 | smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 136 | smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
137 | { | 137 | { |
@@ -139,17 +139,17 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
139 | unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; | 139 | unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; |
140 | unsigned char *sigptr = smb2_signature; | 140 | unsigned char *sigptr = smb2_signature; |
141 | struct kvec *iov = rqst->rq_iov; | 141 | struct kvec *iov = rqst->rq_iov; |
142 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; | 142 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; |
143 | struct cifs_ses *ses; | 143 | struct cifs_ses *ses; |
144 | 144 | ||
145 | ses = smb2_find_smb_ses(smb2_pdu, server); | 145 | ses = smb2_find_smb_ses(server, shdr->SessionId); |
146 | if (!ses) { | 146 | if (!ses) { |
147 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | 147 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); |
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); | 151 | memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); |
152 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); | 152 | memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); |
153 | 153 | ||
154 | rc = smb2_crypto_shash_allocate(server); | 154 | rc = smb2_crypto_shash_allocate(server); |
155 | if (rc) { | 155 | if (rc) { |
@@ -174,7 +174,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
174 | &server->secmech.sdeschmacsha256->shash); | 174 | &server->secmech.sdeschmacsha256->shash); |
175 | 175 | ||
176 | if (!rc) | 176 | if (!rc) |
177 | memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | 177 | memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); |
178 | 178 | ||
179 | return rc; | 179 | return rc; |
180 | } | 180 | } |
@@ -356,17 +356,17 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
356 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; | 356 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; |
357 | unsigned char *sigptr = smb3_signature; | 357 | unsigned char *sigptr = smb3_signature; |
358 | struct kvec *iov = rqst->rq_iov; | 358 | struct kvec *iov = rqst->rq_iov; |
359 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; | 359 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; |
360 | struct cifs_ses *ses; | 360 | struct cifs_ses *ses; |
361 | 361 | ||
362 | ses = smb2_find_smb_ses(smb2_pdu, server); | 362 | ses = smb2_find_smb_ses(server, shdr->SessionId); |
363 | if (!ses) { | 363 | if (!ses) { |
364 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | 364 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); |
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); | 368 | memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); |
369 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); | 369 | memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); |
370 | 370 | ||
371 | rc = crypto_shash_setkey(server->secmech.cmacaes, | 371 | rc = crypto_shash_setkey(server->secmech.cmacaes, |
372 | ses->smb3signingkey, SMB2_CMACAES_SIZE); | 372 | ses->smb3signingkey, SMB2_CMACAES_SIZE); |
@@ -391,7 +391,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
391 | &server->secmech.sdesccmacaes->shash); | 391 | &server->secmech.sdesccmacaes->shash); |
392 | 392 | ||
393 | if (!rc) | 393 | if (!rc) |
394 | memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | 394 | memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); |
395 | 395 | ||
396 | return rc; | 396 | return rc; |
397 | } | 397 | } |
@@ -401,14 +401,15 @@ static int | |||
401 | smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 401 | smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
402 | { | 402 | { |
403 | int rc = 0; | 403 | int rc = 0; |
404 | struct smb2_hdr *smb2_pdu = rqst->rq_iov[0].iov_base; | 404 | struct smb2_sync_hdr *shdr = |
405 | (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; | ||
405 | 406 | ||
406 | if (!(smb2_pdu->Flags & SMB2_FLAGS_SIGNED) || | 407 | if (!(shdr->Flags & SMB2_FLAGS_SIGNED) || |
407 | server->tcpStatus == CifsNeedNegotiate) | 408 | server->tcpStatus == CifsNeedNegotiate) |
408 | return rc; | 409 | return rc; |
409 | 410 | ||
410 | if (!server->session_estab) { | 411 | if (!server->session_estab) { |
411 | strncpy(smb2_pdu->Signature, "BSRSPYL", 8); | 412 | strncpy(shdr->Signature, "BSRSPYL", 8); |
412 | return rc; | 413 | return rc; |
413 | } | 414 | } |
414 | 415 | ||
@@ -422,11 +423,12 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
422 | { | 423 | { |
423 | unsigned int rc; | 424 | unsigned int rc; |
424 | char server_response_sig[16]; | 425 | char server_response_sig[16]; |
425 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; | 426 | struct smb2_sync_hdr *shdr = |
427 | (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; | ||
426 | 428 | ||
427 | if ((smb2_pdu->Command == SMB2_NEGOTIATE) || | 429 | if ((shdr->Command == SMB2_NEGOTIATE) || |
428 | (smb2_pdu->Command == SMB2_SESSION_SETUP) || | 430 | (shdr->Command == SMB2_SESSION_SETUP) || |
429 | (smb2_pdu->Command == SMB2_OPLOCK_BREAK) || | 431 | (shdr->Command == SMB2_OPLOCK_BREAK) || |
430 | (!server->session_estab)) | 432 | (!server->session_estab)) |
431 | return 0; | 433 | return 0; |
432 | 434 | ||
@@ -436,17 +438,17 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
436 | */ | 438 | */ |
437 | 439 | ||
438 | /* Do not need to verify session setups with signature "BSRSPYL " */ | 440 | /* Do not need to verify session setups with signature "BSRSPYL " */ |
439 | if (memcmp(smb2_pdu->Signature, "BSRSPYL ", 8) == 0) | 441 | if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0) |
440 | cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n", | 442 | cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n", |
441 | smb2_pdu->Command); | 443 | shdr->Command); |
442 | 444 | ||
443 | /* | 445 | /* |
444 | * Save off the origiginal signature so we can modify the smb and check | 446 | * Save off the origiginal signature so we can modify the smb and check |
445 | * our calculated signature against what the server sent. | 447 | * our calculated signature against what the server sent. |
446 | */ | 448 | */ |
447 | memcpy(server_response_sig, smb2_pdu->Signature, SMB2_SIGNATURE_SIZE); | 449 | memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE); |
448 | 450 | ||
449 | memset(smb2_pdu->Signature, 0, SMB2_SIGNATURE_SIZE); | 451 | memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE); |
450 | 452 | ||
451 | mutex_lock(&server->srv_mutex); | 453 | mutex_lock(&server->srv_mutex); |
452 | rc = server->ops->calc_signature(rqst, server); | 454 | rc = server->ops->calc_signature(rqst, server); |
@@ -455,8 +457,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
455 | if (rc) | 457 | if (rc) |
456 | return rc; | 458 | return rc; |
457 | 459 | ||
458 | if (memcmp(server_response_sig, smb2_pdu->Signature, | 460 | if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) |
459 | SMB2_SIGNATURE_SIZE)) | ||
460 | return -EACCES; | 461 | return -EACCES; |
461 | else | 462 | else |
462 | return 0; | 463 | return 0; |
@@ -467,18 +468,19 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
467 | * and when srv_mutex is held. | 468 | * and when srv_mutex is held. |
468 | */ | 469 | */ |
469 | static inline void | 470 | static inline void |
470 | smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr) | 471 | smb2_seq_num_into_buf(struct TCP_Server_Info *server, |
472 | struct smb2_sync_hdr *shdr) | ||
471 | { | 473 | { |
472 | unsigned int i, num = le16_to_cpu(hdr->CreditCharge); | 474 | unsigned int i, num = le16_to_cpu(shdr->CreditCharge); |
473 | 475 | ||
474 | hdr->MessageId = get_next_mid64(server); | 476 | shdr->MessageId = get_next_mid64(server); |
475 | /* skip message numbers according to CreditCharge field */ | 477 | /* skip message numbers according to CreditCharge field */ |
476 | for (i = 1; i < num; i++) | 478 | for (i = 1; i < num; i++) |
477 | get_next_mid(server); | 479 | get_next_mid(server); |
478 | } | 480 | } |
479 | 481 | ||
480 | static struct mid_q_entry * | 482 | static struct mid_q_entry * |
481 | smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | 483 | smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr, |
482 | struct TCP_Server_Info *server) | 484 | struct TCP_Server_Info *server) |
483 | { | 485 | { |
484 | struct mid_q_entry *temp; | 486 | struct mid_q_entry *temp; |
@@ -493,9 +495,9 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | |||
493 | return temp; | 495 | return temp; |
494 | else { | 496 | else { |
495 | memset(temp, 0, sizeof(struct mid_q_entry)); | 497 | memset(temp, 0, sizeof(struct mid_q_entry)); |
496 | temp->mid = le64_to_cpu(smb_buffer->MessageId); | 498 | temp->mid = le64_to_cpu(shdr->MessageId); |
497 | temp->pid = current->pid; | 499 | temp->pid = current->pid; |
498 | temp->command = smb_buffer->Command; /* Always LE */ | 500 | temp->command = shdr->Command; /* Always LE */ |
499 | temp->when_alloc = jiffies; | 501 | temp->when_alloc = jiffies; |
500 | temp->server = server; | 502 | temp->server = server; |
501 | 503 | ||
@@ -513,7 +515,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | |||
513 | } | 515 | } |
514 | 516 | ||
515 | static int | 517 | static int |
516 | smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, | 518 | smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_sync_hdr *shdr, |
517 | struct mid_q_entry **mid) | 519 | struct mid_q_entry **mid) |
518 | { | 520 | { |
519 | if (ses->server->tcpStatus == CifsExiting) | 521 | if (ses->server->tcpStatus == CifsExiting) |
@@ -525,19 +527,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, | |||
525 | } | 527 | } |
526 | 528 | ||
527 | if (ses->status == CifsNew) { | 529 | if (ses->status == CifsNew) { |
528 | if ((buf->Command != SMB2_SESSION_SETUP) && | 530 | if ((shdr->Command != SMB2_SESSION_SETUP) && |
529 | (buf->Command != SMB2_NEGOTIATE)) | 531 | (shdr->Command != SMB2_NEGOTIATE)) |
530 | return -EAGAIN; | 532 | return -EAGAIN; |
531 | /* else ok - we are setting up session */ | 533 | /* else ok - we are setting up session */ |
532 | } | 534 | } |
533 | 535 | ||
534 | if (ses->status == CifsExiting) { | 536 | if (ses->status == CifsExiting) { |
535 | if (buf->Command != SMB2_LOGOFF) | 537 | if (shdr->Command != SMB2_LOGOFF) |
536 | return -EAGAIN; | 538 | return -EAGAIN; |
537 | /* else ok - we are shutting down the session */ | 539 | /* else ok - we are shutting down the session */ |
538 | } | 540 | } |
539 | 541 | ||
540 | *mid = smb2_mid_entry_alloc(buf, ses->server); | 542 | *mid = smb2_mid_entry_alloc(shdr, ses->server); |
541 | if (*mid == NULL) | 543 | if (*mid == NULL) |
542 | return -ENOMEM; | 544 | return -ENOMEM; |
543 | spin_lock(&GlobalMid_Lock); | 545 | spin_lock(&GlobalMid_Lock); |
@@ -551,16 +553,18 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
551 | bool log_error) | 553 | bool log_error) |
552 | { | 554 | { |
553 | unsigned int len = get_rfc1002_length(mid->resp_buf); | 555 | unsigned int len = get_rfc1002_length(mid->resp_buf); |
554 | struct kvec iov; | 556 | struct kvec iov[2]; |
555 | struct smb_rqst rqst = { .rq_iov = &iov, | 557 | struct smb_rqst rqst = { .rq_iov = iov, |
556 | .rq_nvec = 1 }; | 558 | .rq_nvec = 2 }; |
557 | 559 | ||
558 | iov.iov_base = (char *)mid->resp_buf; | 560 | iov[0].iov_base = (char *)mid->resp_buf; |
559 | iov.iov_len = get_rfc1002_length(mid->resp_buf) + 4; | 561 | iov[0].iov_len = 4; |
562 | iov[1].iov_base = (char *)mid->resp_buf + 4; | ||
563 | iov[1].iov_len = len; | ||
560 | 564 | ||
561 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); | 565 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); |
562 | /* convert the length into a more usable form */ | 566 | /* convert the length into a more usable form */ |
563 | if (len > 24 && server->sign) { | 567 | if (len > 24 && server->sign && !mid->decrypted) { |
564 | int rc; | 568 | int rc; |
565 | 569 | ||
566 | rc = smb2_verify_signature(&rqst, server); | 570 | rc = smb2_verify_signature(&rqst, server); |
@@ -576,12 +580,13 @@ struct mid_q_entry * | |||
576 | smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) | 580 | smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) |
577 | { | 581 | { |
578 | int rc; | 582 | int rc; |
579 | struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; | 583 | struct smb2_sync_hdr *shdr = |
584 | (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; | ||
580 | struct mid_q_entry *mid; | 585 | struct mid_q_entry *mid; |
581 | 586 | ||
582 | smb2_seq_num_into_buf(ses->server, hdr); | 587 | smb2_seq_num_into_buf(ses->server, shdr); |
583 | 588 | ||
584 | rc = smb2_get_mid_entry(ses, hdr, &mid); | 589 | rc = smb2_get_mid_entry(ses, shdr, &mid); |
585 | if (rc) | 590 | if (rc) |
586 | return ERR_PTR(rc); | 591 | return ERR_PTR(rc); |
587 | rc = smb2_sign_rqst(rqst, ses->server); | 592 | rc = smb2_sign_rqst(rqst, ses->server); |
@@ -596,12 +601,13 @@ struct mid_q_entry * | |||
596 | smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) | 601 | smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) |
597 | { | 602 | { |
598 | int rc; | 603 | int rc; |
599 | struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; | 604 | struct smb2_sync_hdr *shdr = |
605 | (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; | ||
600 | struct mid_q_entry *mid; | 606 | struct mid_q_entry *mid; |
601 | 607 | ||
602 | smb2_seq_num_into_buf(server, hdr); | 608 | smb2_seq_num_into_buf(server, shdr); |
603 | 609 | ||
604 | mid = smb2_mid_entry_alloc(hdr, server); | 610 | mid = smb2_mid_entry_alloc(shdr, server); |
605 | if (mid == NULL) | 611 | if (mid == NULL) |
606 | return ERR_PTR(-ENOMEM); | 612 | return ERR_PTR(-ENOMEM); |
607 | 613 | ||
@@ -613,3 +619,33 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
613 | 619 | ||
614 | return mid; | 620 | return mid; |
615 | } | 621 | } |
622 | |||
623 | int | ||
624 | smb3_crypto_aead_allocate(struct TCP_Server_Info *server) | ||
625 | { | ||
626 | struct crypto_aead *tfm; | ||
627 | |||
628 | if (!server->secmech.ccmaesencrypt) { | ||
629 | tfm = crypto_alloc_aead("ccm(aes)", 0, 0); | ||
630 | if (IS_ERR(tfm)) { | ||
631 | cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n", | ||
632 | __func__); | ||
633 | return PTR_ERR(tfm); | ||
634 | } | ||
635 | server->secmech.ccmaesencrypt = tfm; | ||
636 | } | ||
637 | |||
638 | if (!server->secmech.ccmaesdecrypt) { | ||
639 | tfm = crypto_alloc_aead("ccm(aes)", 0, 0); | ||
640 | if (IS_ERR(tfm)) { | ||
641 | crypto_free_aead(server->secmech.ccmaesencrypt); | ||
642 | server->secmech.ccmaesencrypt = NULL; | ||
643 | cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n", | ||
644 | __func__); | ||
645 | return PTR_ERR(tfm); | ||
646 | } | ||
647 | server->secmech.ccmaesdecrypt = tfm; | ||
648 | } | ||
649 | |||
650 | return 0; | ||
651 | } | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index fbb84c08e3cd..526f0533cb4e 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -221,7 +221,7 @@ rqst_len(struct smb_rqst *rqst) | |||
221 | } | 221 | } |
222 | 222 | ||
223 | static int | 223 | static int |
224 | smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) | 224 | __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) |
225 | { | 225 | { |
226 | int rc; | 226 | int rc; |
227 | struct kvec *iov = rqst->rq_iov; | 227 | struct kvec *iov = rqst->rq_iov; |
@@ -245,8 +245,12 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
245 | return -EIO; | 245 | return -EIO; |
246 | } | 246 | } |
247 | 247 | ||
248 | if (n_vec < 2) | ||
249 | return -EIO; | ||
250 | |||
248 | cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); | 251 | cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); |
249 | dump_smb(iov[0].iov_base, iov[0].iov_len); | 252 | dump_smb(iov[0].iov_base, iov[0].iov_len); |
253 | dump_smb(iov[1].iov_base, iov[1].iov_len); | ||
250 | 254 | ||
251 | /* cork the socket */ | 255 | /* cork the socket */ |
252 | kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, | 256 | kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, |
@@ -309,24 +313,43 @@ uncork: | |||
309 | } | 313 | } |
310 | 314 | ||
311 | static int | 315 | static int |
312 | smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | 316 | smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags) |
313 | { | 317 | { |
314 | struct smb_rqst rqst = { .rq_iov = iov, | 318 | struct smb_rqst cur_rqst; |
315 | .rq_nvec = n_vec }; | 319 | int rc; |
320 | |||
321 | if (!(flags & CIFS_TRANSFORM_REQ)) | ||
322 | return __smb_send_rqst(server, rqst); | ||
323 | |||
324 | if (!server->ops->init_transform_rq || | ||
325 | !server->ops->free_transform_rq) { | ||
326 | cifs_dbg(VFS, "Encryption requested but transform callbacks are missed\n"); | ||
327 | return -EIO; | ||
328 | } | ||
329 | |||
330 | rc = server->ops->init_transform_rq(server, &cur_rqst, rqst); | ||
331 | if (rc) | ||
332 | return rc; | ||
316 | 333 | ||
317 | return smb_send_rqst(server, &rqst); | 334 | rc = __smb_send_rqst(server, &cur_rqst); |
335 | server->ops->free_transform_rq(&cur_rqst); | ||
336 | return rc; | ||
318 | } | 337 | } |
319 | 338 | ||
320 | int | 339 | int |
321 | smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, | 340 | smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, |
322 | unsigned int smb_buf_length) | 341 | unsigned int smb_buf_length) |
323 | { | 342 | { |
324 | struct kvec iov; | 343 | struct kvec iov[2]; |
344 | struct smb_rqst rqst = { .rq_iov = iov, | ||
345 | .rq_nvec = 2 }; | ||
325 | 346 | ||
326 | iov.iov_base = smb_buffer; | 347 | iov[0].iov_base = smb_buffer; |
327 | iov.iov_len = smb_buf_length + 4; | 348 | iov[0].iov_len = 4; |
349 | iov[1].iov_base = (char *)smb_buffer + 4; | ||
350 | iov[1].iov_len = smb_buf_length; | ||
328 | 351 | ||
329 | return smb_sendv(server, &iov, 1); | 352 | return __smb_send_rqst(server, &rqst); |
330 | } | 353 | } |
331 | 354 | ||
332 | static int | 355 | static int |
@@ -454,6 +477,10 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
454 | struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; | 477 | struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; |
455 | struct mid_q_entry *mid; | 478 | struct mid_q_entry *mid; |
456 | 479 | ||
480 | if (rqst->rq_iov[0].iov_len != 4 || | ||
481 | rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) | ||
482 | return ERR_PTR(-EIO); | ||
483 | |||
457 | /* enable signing if server requires it */ | 484 | /* enable signing if server requires it */ |
458 | if (server->sign) | 485 | if (server->sign) |
459 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 486 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
@@ -478,7 +505,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
478 | int | 505 | int |
479 | cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, | 506 | cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, |
480 | mid_receive_t *receive, mid_callback_t *callback, | 507 | mid_receive_t *receive, mid_callback_t *callback, |
481 | void *cbdata, const int flags) | 508 | mid_handle_t *handle, void *cbdata, const int flags) |
482 | { | 509 | { |
483 | int rc, timeout, optype; | 510 | int rc, timeout, optype; |
484 | struct mid_q_entry *mid; | 511 | struct mid_q_entry *mid; |
@@ -505,6 +532,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, | |||
505 | mid->receive = receive; | 532 | mid->receive = receive; |
506 | mid->callback = callback; | 533 | mid->callback = callback; |
507 | mid->callback_data = cbdata; | 534 | mid->callback_data = cbdata; |
535 | mid->handle = handle; | ||
508 | mid->mid_state = MID_REQUEST_SUBMITTED; | 536 | mid->mid_state = MID_REQUEST_SUBMITTED; |
509 | 537 | ||
510 | /* put it on the pending_mid_q */ | 538 | /* put it on the pending_mid_q */ |
@@ -514,7 +542,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, | |||
514 | 542 | ||
515 | 543 | ||
516 | cifs_in_send_inc(server); | 544 | cifs_in_send_inc(server); |
517 | rc = smb_send_rqst(server, rqst); | 545 | rc = smb_send_rqst(server, rqst, flags); |
518 | cifs_in_send_dec(server); | 546 | cifs_in_send_dec(server); |
519 | cifs_save_when_sent(mid); | 547 | cifs_save_when_sent(mid); |
520 | 548 | ||
@@ -547,12 +575,13 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, | |||
547 | { | 575 | { |
548 | int rc; | 576 | int rc; |
549 | struct kvec iov[1]; | 577 | struct kvec iov[1]; |
578 | struct kvec rsp_iov; | ||
550 | int resp_buf_type; | 579 | int resp_buf_type; |
551 | 580 | ||
552 | iov[0].iov_base = in_buf; | 581 | iov[0].iov_base = in_buf; |
553 | iov[0].iov_len = get_rfc1002_length(in_buf) + 4; | 582 | iov[0].iov_len = get_rfc1002_length(in_buf) + 4; |
554 | flags |= CIFS_NO_RESP; | 583 | flags |= CIFS_NO_RESP; |
555 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | 584 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov); |
556 | cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); | 585 | cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); |
557 | 586 | ||
558 | return rc; | 587 | return rc; |
@@ -595,10 +624,11 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
595 | } | 624 | } |
596 | 625 | ||
597 | static inline int | 626 | static inline int |
598 | send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid) | 627 | send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, |
628 | struct mid_q_entry *mid) | ||
599 | { | 629 | { |
600 | return server->ops->send_cancel ? | 630 | return server->ops->send_cancel ? |
601 | server->ops->send_cancel(server, buf, mid) : 0; | 631 | server->ops->send_cancel(server, rqst, mid) : 0; |
602 | } | 632 | } |
603 | 633 | ||
604 | int | 634 | int |
@@ -611,13 +641,15 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
611 | 641 | ||
612 | /* convert the length into a more usable form */ | 642 | /* convert the length into a more usable form */ |
613 | if (server->sign) { | 643 | if (server->sign) { |
614 | struct kvec iov; | 644 | struct kvec iov[2]; |
615 | int rc = 0; | 645 | int rc = 0; |
616 | struct smb_rqst rqst = { .rq_iov = &iov, | 646 | struct smb_rqst rqst = { .rq_iov = iov, |
617 | .rq_nvec = 1 }; | 647 | .rq_nvec = 2 }; |
618 | 648 | ||
619 | iov.iov_base = mid->resp_buf; | 649 | iov[0].iov_base = mid->resp_buf; |
620 | iov.iov_len = len; | 650 | iov[0].iov_len = 4; |
651 | iov[1].iov_base = (char *)mid->resp_buf + 4; | ||
652 | iov[1].iov_len = len - 4; | ||
621 | /* FIXME: add code to kill session */ | 653 | /* FIXME: add code to kill session */ |
622 | rc = cifs_verify_signature(&rqst, server, | 654 | rc = cifs_verify_signature(&rqst, server, |
623 | mid->sequence_number); | 655 | mid->sequence_number); |
@@ -637,6 +669,10 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) | |||
637 | struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; | 669 | struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; |
638 | struct mid_q_entry *mid; | 670 | struct mid_q_entry *mid; |
639 | 671 | ||
672 | if (rqst->rq_iov[0].iov_len != 4 || | ||
673 | rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) | ||
674 | return ERR_PTR(-EIO); | ||
675 | |||
640 | rc = allocate_mid(ses, hdr, &mid); | 676 | rc = allocate_mid(ses, hdr, &mid); |
641 | if (rc) | 677 | if (rc) |
642 | return ERR_PTR(rc); | 678 | return ERR_PTR(rc); |
@@ -649,17 +685,15 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) | |||
649 | } | 685 | } |
650 | 686 | ||
651 | int | 687 | int |
652 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, | 688 | cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, |
653 | struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, | 689 | struct smb_rqst *rqst, int *resp_buf_type, const int flags, |
654 | const int flags) | 690 | struct kvec *resp_iov) |
655 | { | 691 | { |
656 | int rc = 0; | 692 | int rc = 0; |
657 | int timeout, optype; | 693 | int timeout, optype; |
658 | struct mid_q_entry *midQ; | 694 | struct mid_q_entry *midQ; |
659 | char *buf = iov[0].iov_base; | ||
660 | unsigned int credits = 1; | 695 | unsigned int credits = 1; |
661 | struct smb_rqst rqst = { .rq_iov = iov, | 696 | char *buf; |
662 | .rq_nvec = n_vec }; | ||
663 | 697 | ||
664 | timeout = flags & CIFS_TIMEOUT_MASK; | 698 | timeout = flags & CIFS_TIMEOUT_MASK; |
665 | optype = flags & CIFS_OP_MASK; | 699 | optype = flags & CIFS_OP_MASK; |
@@ -667,15 +701,12 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
667 | *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */ | 701 | *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */ |
668 | 702 | ||
669 | if ((ses == NULL) || (ses->server == NULL)) { | 703 | if ((ses == NULL) || (ses->server == NULL)) { |
670 | cifs_small_buf_release(buf); | ||
671 | cifs_dbg(VFS, "Null session\n"); | 704 | cifs_dbg(VFS, "Null session\n"); |
672 | return -EIO; | 705 | return -EIO; |
673 | } | 706 | } |
674 | 707 | ||
675 | if (ses->server->tcpStatus == CifsExiting) { | 708 | if (ses->server->tcpStatus == CifsExiting) |
676 | cifs_small_buf_release(buf); | ||
677 | return -ENOENT; | 709 | return -ENOENT; |
678 | } | ||
679 | 710 | ||
680 | /* | 711 | /* |
681 | * Ensure that we do not send more than 50 overlapping requests | 712 | * Ensure that we do not send more than 50 overlapping requests |
@@ -684,10 +715,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
684 | */ | 715 | */ |
685 | 716 | ||
686 | rc = wait_for_free_request(ses->server, timeout, optype); | 717 | rc = wait_for_free_request(ses->server, timeout, optype); |
687 | if (rc) { | 718 | if (rc) |
688 | cifs_small_buf_release(buf); | ||
689 | return rc; | 719 | return rc; |
690 | } | ||
691 | 720 | ||
692 | /* | 721 | /* |
693 | * Make sure that we sign in the same order that we send on this socket | 722 | * Make sure that we sign in the same order that we send on this socket |
@@ -697,10 +726,9 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
697 | 726 | ||
698 | mutex_lock(&ses->server->srv_mutex); | 727 | mutex_lock(&ses->server->srv_mutex); |
699 | 728 | ||
700 | midQ = ses->server->ops->setup_request(ses, &rqst); | 729 | midQ = ses->server->ops->setup_request(ses, rqst); |
701 | if (IS_ERR(midQ)) { | 730 | if (IS_ERR(midQ)) { |
702 | mutex_unlock(&ses->server->srv_mutex); | 731 | mutex_unlock(&ses->server->srv_mutex); |
703 | cifs_small_buf_release(buf); | ||
704 | /* Update # of requests on wire to server */ | 732 | /* Update # of requests on wire to server */ |
705 | add_credits(ses->server, 1, optype); | 733 | add_credits(ses->server, 1, optype); |
706 | return PTR_ERR(midQ); | 734 | return PTR_ERR(midQ); |
@@ -708,7 +736,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
708 | 736 | ||
709 | midQ->mid_state = MID_REQUEST_SUBMITTED; | 737 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
710 | cifs_in_send_inc(ses->server); | 738 | cifs_in_send_inc(ses->server); |
711 | rc = smb_sendv(ses->server, iov, n_vec); | 739 | rc = smb_send_rqst(ses->server, rqst, flags); |
712 | cifs_in_send_dec(ses->server); | 740 | cifs_in_send_dec(ses->server); |
713 | cifs_save_when_sent(midQ); | 741 | cifs_save_when_sent(midQ); |
714 | 742 | ||
@@ -716,32 +744,25 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
716 | ses->server->sequence_number -= 2; | 744 | ses->server->sequence_number -= 2; |
717 | mutex_unlock(&ses->server->srv_mutex); | 745 | mutex_unlock(&ses->server->srv_mutex); |
718 | 746 | ||
719 | if (rc < 0) { | 747 | if (rc < 0) |
720 | cifs_small_buf_release(buf); | ||
721 | goto out; | 748 | goto out; |
722 | } | ||
723 | 749 | ||
724 | if (timeout == CIFS_ASYNC_OP) { | 750 | if (timeout == CIFS_ASYNC_OP) |
725 | cifs_small_buf_release(buf); | ||
726 | goto out; | 751 | goto out; |
727 | } | ||
728 | 752 | ||
729 | rc = wait_for_response(ses->server, midQ); | 753 | rc = wait_for_response(ses->server, midQ); |
730 | if (rc != 0) { | 754 | if (rc != 0) { |
731 | send_cancel(ses->server, buf, midQ); | 755 | send_cancel(ses->server, rqst, midQ); |
732 | spin_lock(&GlobalMid_Lock); | 756 | spin_lock(&GlobalMid_Lock); |
733 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | 757 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
734 | midQ->callback = DeleteMidQEntry; | 758 | midQ->callback = DeleteMidQEntry; |
735 | spin_unlock(&GlobalMid_Lock); | 759 | spin_unlock(&GlobalMid_Lock); |
736 | cifs_small_buf_release(buf); | ||
737 | add_credits(ses->server, 1, optype); | 760 | add_credits(ses->server, 1, optype); |
738 | return rc; | 761 | return rc; |
739 | } | 762 | } |
740 | spin_unlock(&GlobalMid_Lock); | 763 | spin_unlock(&GlobalMid_Lock); |
741 | } | 764 | } |
742 | 765 | ||
743 | cifs_small_buf_release(buf); | ||
744 | |||
745 | rc = cifs_sync_mid_result(midQ, ses->server); | 766 | rc = cifs_sync_mid_result(midQ, ses->server); |
746 | if (rc != 0) { | 767 | if (rc != 0) { |
747 | add_credits(ses->server, 1, optype); | 768 | add_credits(ses->server, 1, optype); |
@@ -755,8 +776,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
755 | } | 776 | } |
756 | 777 | ||
757 | buf = (char *)midQ->resp_buf; | 778 | buf = (char *)midQ->resp_buf; |
758 | iov[0].iov_base = buf; | 779 | resp_iov->iov_base = buf; |
759 | iov[0].iov_len = get_rfc1002_length(buf) + 4; | 780 | resp_iov->iov_len = get_rfc1002_length(buf) + 4; |
760 | if (midQ->large_buf) | 781 | if (midQ->large_buf) |
761 | *resp_buf_type = CIFS_LARGE_BUFFER; | 782 | *resp_buf_type = CIFS_LARGE_BUFFER; |
762 | else | 783 | else |
@@ -778,12 +799,45 @@ out: | |||
778 | } | 799 | } |
779 | 800 | ||
780 | int | 801 | int |
802 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, | ||
803 | struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, | ||
804 | const int flags, struct kvec *resp_iov) | ||
805 | { | ||
806 | struct smb_rqst rqst; | ||
807 | struct kvec *new_iov; | ||
808 | int rc; | ||
809 | |||
810 | new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL); | ||
811 | if (!new_iov) | ||
812 | return -ENOMEM; | ||
813 | |||
814 | /* 1st iov is a RFC1001 length followed by the rest of the packet */ | ||
815 | memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); | ||
816 | |||
817 | new_iov[0].iov_base = new_iov[1].iov_base; | ||
818 | new_iov[0].iov_len = 4; | ||
819 | new_iov[1].iov_base += 4; | ||
820 | new_iov[1].iov_len -= 4; | ||
821 | |||
822 | memset(&rqst, 0, sizeof(struct smb_rqst)); | ||
823 | rqst.rq_iov = new_iov; | ||
824 | rqst.rq_nvec = n_vec + 1; | ||
825 | |||
826 | rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); | ||
827 | kfree(new_iov); | ||
828 | return rc; | ||
829 | } | ||
830 | |||
831 | int | ||
781 | SendReceive(const unsigned int xid, struct cifs_ses *ses, | 832 | SendReceive(const unsigned int xid, struct cifs_ses *ses, |
782 | struct smb_hdr *in_buf, struct smb_hdr *out_buf, | 833 | struct smb_hdr *in_buf, struct smb_hdr *out_buf, |
783 | int *pbytes_returned, const int timeout) | 834 | int *pbytes_returned, const int timeout) |
784 | { | 835 | { |
785 | int rc = 0; | 836 | int rc = 0; |
786 | struct mid_q_entry *midQ; | 837 | struct mid_q_entry *midQ; |
838 | unsigned int len = be32_to_cpu(in_buf->smb_buf_length); | ||
839 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; | ||
840 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; | ||
787 | 841 | ||
788 | if (ses == NULL) { | 842 | if (ses == NULL) { |
789 | cifs_dbg(VFS, "Null smb session\n"); | 843 | cifs_dbg(VFS, "Null smb session\n"); |
@@ -801,10 +855,9 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
801 | to the same server. We may make this configurable later or | 855 | to the same server. We may make this configurable later or |
802 | use ses->maxReq */ | 856 | use ses->maxReq */ |
803 | 857 | ||
804 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + | 858 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
805 | MAX_CIFS_HDR_SIZE - 4) { | ||
806 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", | 859 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", |
807 | be32_to_cpu(in_buf->smb_buf_length)); | 860 | len); |
808 | return -EIO; | 861 | return -EIO; |
809 | } | 862 | } |
810 | 863 | ||
@@ -835,7 +888,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
835 | midQ->mid_state = MID_REQUEST_SUBMITTED; | 888 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
836 | 889 | ||
837 | cifs_in_send_inc(ses->server); | 890 | cifs_in_send_inc(ses->server); |
838 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); | 891 | rc = smb_send(ses->server, in_buf, len); |
839 | cifs_in_send_dec(ses->server); | 892 | cifs_in_send_dec(ses->server); |
840 | cifs_save_when_sent(midQ); | 893 | cifs_save_when_sent(midQ); |
841 | 894 | ||
@@ -852,7 +905,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
852 | 905 | ||
853 | rc = wait_for_response(ses->server, midQ); | 906 | rc = wait_for_response(ses->server, midQ); |
854 | if (rc != 0) { | 907 | if (rc != 0) { |
855 | send_cancel(ses->server, in_buf, midQ); | 908 | send_cancel(ses->server, &rqst, midQ); |
856 | spin_lock(&GlobalMid_Lock); | 909 | spin_lock(&GlobalMid_Lock); |
857 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | 910 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
858 | /* no longer considered to be "in-flight" */ | 911 | /* no longer considered to be "in-flight" */ |
@@ -921,6 +974,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
921 | int rstart = 0; | 974 | int rstart = 0; |
922 | struct mid_q_entry *midQ; | 975 | struct mid_q_entry *midQ; |
923 | struct cifs_ses *ses; | 976 | struct cifs_ses *ses; |
977 | unsigned int len = be32_to_cpu(in_buf->smb_buf_length); | ||
978 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; | ||
979 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; | ||
924 | 980 | ||
925 | if (tcon == NULL || tcon->ses == NULL) { | 981 | if (tcon == NULL || tcon->ses == NULL) { |
926 | cifs_dbg(VFS, "Null smb session\n"); | 982 | cifs_dbg(VFS, "Null smb session\n"); |
@@ -940,10 +996,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
940 | to the same server. We may make this configurable later or | 996 | to the same server. We may make this configurable later or |
941 | use ses->maxReq */ | 997 | use ses->maxReq */ |
942 | 998 | ||
943 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + | 999 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
944 | MAX_CIFS_HDR_SIZE - 4) { | ||
945 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", | 1000 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", |
946 | be32_to_cpu(in_buf->smb_buf_length)); | 1001 | len); |
947 | return -EIO; | 1002 | return -EIO; |
948 | } | 1003 | } |
949 | 1004 | ||
@@ -972,7 +1027,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
972 | 1027 | ||
973 | midQ->mid_state = MID_REQUEST_SUBMITTED; | 1028 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
974 | cifs_in_send_inc(ses->server); | 1029 | cifs_in_send_inc(ses->server); |
975 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); | 1030 | rc = smb_send(ses->server, in_buf, len); |
976 | cifs_in_send_dec(ses->server); | 1031 | cifs_in_send_dec(ses->server); |
977 | cifs_save_when_sent(midQ); | 1032 | cifs_save_when_sent(midQ); |
978 | 1033 | ||
@@ -1001,7 +1056,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1001 | if (in_buf->Command == SMB_COM_TRANSACTION2) { | 1056 | if (in_buf->Command == SMB_COM_TRANSACTION2) { |
1002 | /* POSIX lock. We send a NT_CANCEL SMB to cause the | 1057 | /* POSIX lock. We send a NT_CANCEL SMB to cause the |
1003 | blocking lock to return. */ | 1058 | blocking lock to return. */ |
1004 | rc = send_cancel(ses->server, in_buf, midQ); | 1059 | rc = send_cancel(ses->server, &rqst, midQ); |
1005 | if (rc) { | 1060 | if (rc) { |
1006 | cifs_delete_mid(midQ); | 1061 | cifs_delete_mid(midQ); |
1007 | return rc; | 1062 | return rc; |
@@ -1022,7 +1077,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1022 | 1077 | ||
1023 | rc = wait_for_response(ses->server, midQ); | 1078 | rc = wait_for_response(ses->server, midQ); |
1024 | if (rc) { | 1079 | if (rc) { |
1025 | send_cancel(ses->server, in_buf, midQ); | 1080 | send_cancel(ses->server, &rqst, midQ); |
1026 | spin_lock(&GlobalMid_Lock); | 1081 | spin_lock(&GlobalMid_Lock); |
1027 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | 1082 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
1028 | /* no longer considered to be "in-flight" */ | 1083 | /* no longer considered to be "in-flight" */ |