aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2018-06-11 18:00:58 -0400
committerSteve French <stfrench@microsoft.com>2018-06-15 03:38:08 -0400
commitc713c8770fa5bfbeaac088cc7b959c7a6ba79f93 (patch)
tree76b49e4511ff8b37777552aa150caae3033ce77c
parentd409014e4feeab486fb36b350abfc4c94de8be37 (diff)
cifs: push rfc1002 generation down the stack
Move the generation of the 4 byte length field down the stack and generate it immediately before we start writing the data to the socket. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/cifsencrypt.c23
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/smb2ops.c71
-rw-r--r--fs/cifs/smb2pdu.c38
-rw-r--r--fs/cifs/smb2transport.c18
-rw-r--r--fs/cifs/transport.c82
6 files changed, 99 insertions, 135 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 937251cc61c0..f23ff848b158 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,7 +37,6 @@
37#include <crypto/aead.h> 37#include <crypto/aead.h>
38 38
39int __cifs_calc_signature(struct smb_rqst *rqst, 39int __cifs_calc_signature(struct smb_rqst *rqst,
40 int start,
41 struct TCP_Server_Info *server, char *signature, 40 struct TCP_Server_Info *server, char *signature,
42 struct shash_desc *shash) 41 struct shash_desc *shash)
43{ 42{
@@ -45,16 +44,30 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
45 int rc; 44 int rc;
46 struct kvec *iov = rqst->rq_iov; 45 struct kvec *iov = rqst->rq_iov;
47 int n_vec = rqst->rq_nvec; 46 int n_vec = rqst->rq_nvec;
47 int is_smb2 = server->vals->header_preamble_size == 0;
48 48
49 for (i = start; i < n_vec; i++) { 49 /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
50 if (is_smb2) {
51 rc = crypto_shash_update(shash,
52 iov[0].iov_base, iov[0].iov_len);
53 } else {
54 if (n_vec < 2 || iov[0].iov_len != 4)
55 return -EIO;
56 }
57
58 for (i = 1; i < n_vec; i++) {
50 if (iov[i].iov_len == 0) 59 if (iov[i].iov_len == 0)
51 continue; 60 continue;
52 if (iov[i].iov_base == NULL) { 61 if (iov[i].iov_base == NULL) {
53 cifs_dbg(VFS, "null iovec entry\n"); 62 cifs_dbg(VFS, "null iovec entry\n");
54 return -EIO; 63 return -EIO;
55 } 64 }
56 if (i == 1 && iov[1].iov_len <= 4) 65 if (is_smb2) {
57 break; /* nothing to sign or corrupt header */ 66 if (i == 0 && iov[0].iov_len <= 4)
67 break; /* nothing to sign or corrupt header */
68 } else
69 if (i == 1 && iov[1].iov_len <= 4)
70 break; /* nothing to sign or corrupt header */
58 rc = crypto_shash_update(shash, 71 rc = crypto_shash_update(shash,
59 iov[i].iov_base, iov[i].iov_len); 72 iov[i].iov_base, iov[i].iov_len);
60 if (rc) { 73 if (rc) {
@@ -118,7 +131,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
118 return rc; 131 return rc;
119 } 132 }
120 133
121 return __cifs_calc_signature(rqst, 1, server, signature, 134 return __cifs_calc_signature(rqst, server, signature,
122 &server->secmech.sdescmd5->shash); 135 &server->secmech.sdescmd5->shash);
123} 136}
124 137
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 3a13b44069fe..4f9218281ff3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
544 struct cifs_sb_info *cifs_sb, 544 struct cifs_sb_info *cifs_sb,
545 const unsigned char *path, char *pbuf, 545 const unsigned char *path, char *pbuf,
546 unsigned int *pbytes_written); 546 unsigned int *pbytes_written);
547int __cifs_calc_signature(struct smb_rqst *rqst, int start, 547int __cifs_calc_signature(struct smb_rqst *rqst,
548 struct TCP_Server_Info *server, char *signature, 548 struct TCP_Server_Info *server, char *signature,
549 struct shash_desc *shash); 549 struct shash_desc *shash);
550enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, 550enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 682bcfa246be..9153407f97e8 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2167,7 +2167,7 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
2167 struct smb_rqst *old_rq) 2167 struct smb_rqst *old_rq)
2168{ 2168{
2169 struct smb2_sync_hdr *shdr = 2169 struct smb2_sync_hdr *shdr =
2170 (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base; 2170 (struct smb2_sync_hdr *)old_rq->rq_iov[0].iov_base;
2171 2171
2172 memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); 2172 memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
2173 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; 2173 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
@@ -2187,14 +2187,13 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
2187} 2187}
2188 2188
2189/* Assumes: 2189/* Assumes:
2190 * rqst->rq_iov[0] is rfc1002 length 2190 * rqst->rq_iov[0] is tranform header
2191 * rqst->rq_iov[1] is tranform header 2191 * rqst->rq_iov[1+] data to be encrypted/decrypted
2192 * rqst->rq_iov[2+] data to be encrypted/decrypted
2193 */ 2192 */
2194static struct scatterlist * 2193static struct scatterlist *
2195init_sg(struct smb_rqst *rqst, u8 *sign) 2194init_sg(struct smb_rqst *rqst, u8 *sign)
2196{ 2195{
2197 unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages; 2196 unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
2198 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; 2197 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
2199 struct scatterlist *sg; 2198 struct scatterlist *sg;
2200 unsigned int i; 2199 unsigned int i;
@@ -2205,10 +2204,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
2205 return NULL; 2204 return NULL;
2206 2205
2207 sg_init_table(sg, sg_len); 2206 sg_init_table(sg, sg_len);
2208 smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len); 2207 smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 20, assoc_data_len);
2209 for (i = 1; i < rqst->rq_nvec - 1; i++) 2208 for (i = 1; i < rqst->rq_nvec; i++)
2210 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base, 2209 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
2211 rqst->rq_iov[i+1].iov_len); 2210 rqst->rq_iov[i].iov_len);
2212 for (j = 0; i < sg_len - 1; i++, j++) { 2211 for (j = 0; i < sg_len - 1; i++, j++) {
2213 unsigned int len, offset; 2212 unsigned int len, offset;
2214 2213
@@ -2240,11 +2239,10 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
2240 return 1; 2239 return 1;
2241} 2240}
2242/* 2241/*
2243 * Encrypt or decrypt @rqst message. @rqst has the following format: 2242 * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
2244 * iov[0] - rfc1002 length 2243 * iov[0] - transform header (associate data),
2245 * iov[1] - transform header (associate data), 2244 * iov[1-N] - SMB2 header and pages - data to encrypt.
2246 * iov[2-N] and pages - data to encrypt. 2245 * On success return encrypted data in iov[1-N] and pages, leave iov[0]
2247 * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
2248 * untouched. 2246 * untouched.
2249 */ 2247 */
2250static int 2248static int
@@ -2339,10 +2337,6 @@ free_req:
2339 return rc; 2337 return rc;
2340} 2338}
2341 2339
2342/*
2343 * This is called from smb_send_rqst. At this point we have the rfc1002
2344 * header as the first element in the vector.
2345 */
2346static int 2340static int
2347smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, 2341smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2348 struct smb_rqst *old_rq) 2342 struct smb_rqst *old_rq)
@@ -2351,7 +2345,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2351 struct page **pages; 2345 struct page **pages;
2352 struct smb2_transform_hdr *tr_hdr; 2346 struct smb2_transform_hdr *tr_hdr;
2353 unsigned int npages = old_rq->rq_npages; 2347 unsigned int npages = old_rq->rq_npages;
2354 unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); 2348 unsigned int orig_len = 0;
2355 int i; 2349 int i;
2356 int rc = -ENOMEM; 2350 int rc = -ENOMEM;
2357 2351
@@ -2365,24 +2359,23 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2365 new_rq->rq_pagesz = old_rq->rq_pagesz; 2359 new_rq->rq_pagesz = old_rq->rq_pagesz;
2366 new_rq->rq_tailsz = old_rq->rq_tailsz; 2360 new_rq->rq_tailsz = old_rq->rq_tailsz;
2367 2361
2362 for (i = 0; i < old_rq->rq_nvec; i++)
2363 orig_len += old_rq->rq_iov[i].iov_len;
2364
2368 for (i = 0; i < npages; i++) { 2365 for (i = 0; i < npages; i++) {
2369 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); 2366 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2370 if (!pages[i]) 2367 if (!pages[i])
2371 goto err_free_pages; 2368 goto err_free_pages;
2372 } 2369 }
2373 2370
2374 /* Make space for one extra iov to hold the transform header */
2375 iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec), 2371 iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
2376 GFP_KERNEL); 2372 GFP_KERNEL);
2377 if (!iov) 2373 if (!iov)
2378 goto err_free_pages; 2374 goto err_free_pages;
2379 2375
2380 /* copy all iovs from the old except the 1st one (rfc1002 length) */ 2376 /* copy all iovs from the old */
2381 memcpy(&iov[2], &old_rq->rq_iov[1], 2377 memcpy(&iov[1], &old_rq->rq_iov[0],
2382 sizeof(struct kvec) * (old_rq->rq_nvec - 1)); 2378 sizeof(struct kvec) * old_rq->rq_nvec);
2383 /* copy the rfc1002 iov */
2384 iov[0].iov_base = old_rq->rq_iov[0].iov_base;
2385 iov[0].iov_len = old_rq->rq_iov[0].iov_len;
2386 2379
2387 new_rq->rq_iov = iov; 2380 new_rq->rq_iov = iov;
2388 new_rq->rq_nvec = old_rq->rq_nvec + 1; 2381 new_rq->rq_nvec = old_rq->rq_nvec + 1;
@@ -2393,12 +2386,8 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2393 2386
2394 /* fill the 2nd iov with a transform header */ 2387 /* fill the 2nd iov with a transform header */
2395 fill_transform_hdr(tr_hdr, orig_len, old_rq); 2388 fill_transform_hdr(tr_hdr, orig_len, old_rq);
2396 new_rq->rq_iov[1].iov_base = tr_hdr; 2389 new_rq->rq_iov[0].iov_base = tr_hdr;
2397 new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr); 2390 new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
2398
2399 /* Update rfc1002 header */
2400 inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
2401 sizeof(struct smb2_transform_hdr));
2402 2391
2403 /* copy pages form the old */ 2392 /* copy pages form the old */
2404 for (i = 0; i < npages; i++) { 2393 for (i = 0; i < npages; i++) {
@@ -2442,7 +2431,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst)
2442 put_page(rqst->rq_pages[i]); 2431 put_page(rqst->rq_pages[i]);
2443 kfree(rqst->rq_pages); 2432 kfree(rqst->rq_pages);
2444 /* free transform header */ 2433 /* free transform header */
2445 kfree(rqst->rq_iov[1].iov_base); 2434 kfree(rqst->rq_iov[0].iov_base);
2446 kfree(rqst->rq_iov); 2435 kfree(rqst->rq_iov);
2447} 2436}
2448 2437
@@ -2459,19 +2448,17 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
2459 unsigned int buf_data_size, struct page **pages, 2448 unsigned int buf_data_size, struct page **pages,
2460 unsigned int npages, unsigned int page_data_size) 2449 unsigned int npages, unsigned int page_data_size)
2461{ 2450{
2462 struct kvec iov[3]; 2451 struct kvec iov[2];
2463 struct smb_rqst rqst = {NULL}; 2452 struct smb_rqst rqst = {NULL};
2464 int rc; 2453 int rc;
2465 2454
2466 iov[0].iov_base = NULL; 2455 iov[0].iov_base = buf;
2467 iov[0].iov_len = 0; 2456 iov[0].iov_len = sizeof(struct smb2_transform_hdr);
2468 iov[1].iov_base = buf; 2457 iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
2469 iov[1].iov_len = sizeof(struct smb2_transform_hdr); 2458 iov[1].iov_len = buf_data_size;
2470 iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
2471 iov[2].iov_len = buf_data_size;
2472 2459
2473 rqst.rq_iov = iov; 2460 rqst.rq_iov = iov;
2474 rqst.rq_nvec = 3; 2461 rqst.rq_nvec = 2;
2475 rqst.rq_pages = pages; 2462 rqst.rq_pages = pages;
2476 rqst.rq_npages = npages; 2463 rqst.rq_npages = npages;
2477 rqst.rq_pagesz = PAGE_SIZE; 2464 rqst.rq_pagesz = PAGE_SIZE;
@@ -2483,7 +2470,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
2483 if (rc) 2470 if (rc)
2484 return rc; 2471 return rc;
2485 2472
2486 memmove(buf, iov[2].iov_base, buf_data_size); 2473 memmove(buf, iov[1].iov_base, buf_data_size);
2487 2474
2488 server->total_read = buf_data_size + page_data_size; 2475 server->total_read = buf_data_size + page_data_size;
2489 2476
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 328e23abd241..c48608c5a0fb 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2595,11 +2595,10 @@ SMB2_echo(struct TCP_Server_Info *server)
2595{ 2595{
2596 struct smb2_echo_req *req; 2596 struct smb2_echo_req *req;
2597 int rc = 0; 2597 int rc = 0;
2598 struct kvec iov[2]; 2598 struct kvec iov[1];
2599 struct smb_rqst rqst = { .rq_iov = iov, 2599 struct smb_rqst rqst = { .rq_iov = iov,
2600 .rq_nvec = 2 }; 2600 .rq_nvec = 1 };
2601 unsigned int total_len; 2601 unsigned int total_len;
2602 __be32 rfc1002_marker;
2603 2602
2604 cifs_dbg(FYI, "In echo request\n"); 2603 cifs_dbg(FYI, "In echo request\n");
2605 2604
@@ -2615,11 +2614,8 @@ SMB2_echo(struct TCP_Server_Info *server)
2615 2614
2616 req->sync_hdr.CreditRequest = cpu_to_le16(1); 2615 req->sync_hdr.CreditRequest = cpu_to_le16(1);
2617 2616
2618 iov[0].iov_len = 4; 2617 iov[0].iov_len = total_len;
2619 rfc1002_marker = cpu_to_be32(total_len); 2618 iov[0].iov_base = (char *)req;
2620 iov[0].iov_base = &rfc1002_marker;
2621 iov[1].iov_len = total_len;
2622 iov[1].iov_base = (char *)req;
2623 2619
2624 rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, 2620 rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
2625 server, CIFS_ECHO_OP); 2621 server, CIFS_ECHO_OP);
@@ -2849,10 +2845,9 @@ smb2_async_readv(struct cifs_readdata *rdata)
2849 struct smb2_sync_hdr *shdr; 2845 struct smb2_sync_hdr *shdr;
2850 struct cifs_io_parms io_parms; 2846 struct cifs_io_parms io_parms;
2851 struct smb_rqst rqst = { .rq_iov = rdata->iov, 2847 struct smb_rqst rqst = { .rq_iov = rdata->iov,
2852 .rq_nvec = 2 }; 2848 .rq_nvec = 1 };
2853 struct TCP_Server_Info *server; 2849 struct TCP_Server_Info *server;
2854 unsigned int total_len; 2850 unsigned int total_len;
2855 __be32 req_len;
2856 2851
2857 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", 2852 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
2858 __func__, rdata->offset, rdata->bytes); 2853 __func__, rdata->offset, rdata->bytes);
@@ -2883,12 +2878,8 @@ smb2_async_readv(struct cifs_readdata *rdata)
2883 if (smb3_encryption_required(io_parms.tcon)) 2878 if (smb3_encryption_required(io_parms.tcon))
2884 flags |= CIFS_TRANSFORM_REQ; 2879 flags |= CIFS_TRANSFORM_REQ;
2885 2880
2886 req_len = cpu_to_be32(total_len); 2881 rdata->iov[0].iov_base = buf;
2887 2882 rdata->iov[0].iov_len = total_len;
2888 rdata->iov[0].iov_base = &req_len;
2889 rdata->iov[0].iov_len = sizeof(__be32);
2890 rdata->iov[1].iov_base = buf;
2891 rdata->iov[1].iov_len = total_len;
2892 2883
2893 shdr = (struct smb2_sync_hdr *)buf; 2884 shdr = (struct smb2_sync_hdr *)buf;
2894 2885
@@ -3063,10 +3054,9 @@ smb2_async_writev(struct cifs_writedata *wdata,
3063 struct smb2_sync_hdr *shdr; 3054 struct smb2_sync_hdr *shdr;
3064 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 3055 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
3065 struct TCP_Server_Info *server = tcon->ses->server; 3056 struct TCP_Server_Info *server = tcon->ses->server;
3066 struct kvec iov[2]; 3057 struct kvec iov[1];
3067 struct smb_rqst rqst = { }; 3058 struct smb_rqst rqst = { };
3068 unsigned int total_len; 3059 unsigned int total_len;
3069 __be32 rfc1002_marker;
3070 3060
3071 rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len); 3061 rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len);
3072 if (rc) { 3062 if (rc) {
@@ -3138,15 +3128,11 @@ smb2_async_writev(struct cifs_writedata *wdata,
3138 v1->length = cpu_to_le32(wdata->mr->mr->length); 3128 v1->length = cpu_to_le32(wdata->mr->mr->length);
3139 } 3129 }
3140#endif 3130#endif
3141 /* 4 for rfc1002 length field and 1 for Buffer */ 3131 iov[0].iov_len = total_len - 1;
3142 iov[0].iov_len = 4; 3132 iov[0].iov_base = (char *)req;
3143 rfc1002_marker = cpu_to_be32(total_len - 1 + wdata->bytes);
3144 iov[0].iov_base = &rfc1002_marker;
3145 iov[1].iov_len = total_len - 1;
3146 iov[1].iov_base = (char *)req;
3147 3133
3148 rqst.rq_iov = iov; 3134 rqst.rq_iov = iov;
3149 rqst.rq_nvec = 2; 3135 rqst.rq_nvec = 1;
3150 rqst.rq_pages = wdata->pages; 3136 rqst.rq_pages = wdata->pages;
3151 rqst.rq_offset = wdata->page_offset; 3137 rqst.rq_offset = wdata->page_offset;
3152 rqst.rq_npages = wdata->nr_pages; 3138 rqst.rq_npages = wdata->nr_pages;
@@ -3154,7 +3140,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
3154 rqst.rq_tailsz = wdata->tailsz; 3140 rqst.rq_tailsz = wdata->tailsz;
3155#ifdef CONFIG_CIFS_SMB_DIRECT 3141#ifdef CONFIG_CIFS_SMB_DIRECT
3156 if (wdata->mr) { 3142 if (wdata->mr) {
3157 iov[1].iov_len += sizeof(struct smbd_buffer_descriptor_v1); 3143 iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
3158 rqst.rq_npages = 0; 3144 rqst.rq_npages = 0;
3159 } 3145 }
3160#endif 3146#endif
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 349d5ccf854c..51b9437c3c7b 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -171,9 +171,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; 171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
172 unsigned char *sigptr = smb2_signature; 172 unsigned char *sigptr = smb2_signature;
173 struct kvec *iov = rqst->rq_iov; 173 struct kvec *iov = rqst->rq_iov;
174 int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0; 174 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
175 struct smb2_sync_hdr *shdr =
176 (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
177 struct cifs_ses *ses; 175 struct cifs_ses *ses;
178 176
179 ses = smb2_find_smb_ses(server, shdr->SessionId); 177 ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -204,7 +202,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
204 return rc; 202 return rc;
205 } 203 }
206 204
207 rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr, 205 rc = __cifs_calc_signature(rqst, server, sigptr,
208 &server->secmech.sdeschmacsha256->shash); 206 &server->secmech.sdeschmacsha256->shash);
209 207
210 if (!rc) 208 if (!rc)
@@ -414,9 +412,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
414 unsigned char smb3_signature[SMB2_CMACAES_SIZE]; 412 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
415 unsigned char *sigptr = smb3_signature; 413 unsigned char *sigptr = smb3_signature;
416 struct kvec *iov = rqst->rq_iov; 414 struct kvec *iov = rqst->rq_iov;
417 int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0; 415 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
418 struct smb2_sync_hdr *shdr =
419 (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
420 struct cifs_ses *ses; 416 struct cifs_ses *ses;
421 417
422 ses = smb2_find_smb_ses(server, shdr->SessionId); 418 ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -447,7 +443,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
447 return rc; 443 return rc;
448 } 444 }
449 445
450 rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr, 446 rc = __cifs_calc_signature(rqst, server, sigptr,
451 &server->secmech.sdesccmacaes->shash); 447 &server->secmech.sdesccmacaes->shash);
452 448
453 if (!rc) 449 if (!rc)
@@ -462,7 +458,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
462{ 458{
463 int rc = 0; 459 int rc = 0;
464 struct smb2_sync_hdr *shdr = 460 struct smb2_sync_hdr *shdr =
465 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; 461 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
466 462
467 if (!(shdr->Flags & SMB2_FLAGS_SIGNED) || 463 if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
468 server->tcpStatus == CifsNeedNegotiate) 464 server->tcpStatus == CifsNeedNegotiate)
@@ -635,7 +631,7 @@ smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
635{ 631{
636 int rc; 632 int rc;
637 struct smb2_sync_hdr *shdr = 633 struct smb2_sync_hdr *shdr =
638 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; 634 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
639 struct mid_q_entry *mid; 635 struct mid_q_entry *mid;
640 636
641 smb2_seq_num_into_buf(ses->server, shdr); 637 smb2_seq_num_into_buf(ses->server, shdr);
@@ -656,7 +652,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
656{ 652{
657 int rc; 653 int rc;
658 struct smb2_sync_hdr *shdr = 654 struct smb2_sync_hdr *shdr =
659 (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; 655 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
660 struct mid_q_entry *mid; 656 struct mid_q_entry *mid;
661 657
662 smb2_seq_num_into_buf(server, shdr); 658 smb2_seq_num_into_buf(server, shdr);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 1f1a68f89110..63f25f919b24 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -241,13 +241,14 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
241 int rc; 241 int rc;
242 struct kvec *iov = rqst->rq_iov; 242 struct kvec *iov = rqst->rq_iov;
243 int n_vec = rqst->rq_nvec; 243 int n_vec = rqst->rq_nvec;
244 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); 244 unsigned int send_length;
245 unsigned long send_length;
246 unsigned int i; 245 unsigned int i;
247 size_t total_len = 0, sent, size; 246 size_t total_len = 0, sent, size;
248 struct socket *ssocket = server->ssocket; 247 struct socket *ssocket = server->ssocket;
249 struct msghdr smb_msg; 248 struct msghdr smb_msg;
250 int val = 1; 249 int val = 1;
250 __be32 rfc1002_marker;
251
251 if (cifs_rdma_enabled(server) && server->smbd_conn) { 252 if (cifs_rdma_enabled(server) && server->smbd_conn) {
252 rc = smbd_send(server->smbd_conn, rqst); 253 rc = smbd_send(server->smbd_conn, rqst);
253 goto smbd_done; 254 goto smbd_done;
@@ -255,26 +256,34 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
255 if (ssocket == NULL) 256 if (ssocket == NULL)
256 return -ENOTSOCK; 257 return -ENOTSOCK;
257 258
258 /* sanity check send length */
259 send_length = rqst_len(rqst); 259 send_length = rqst_len(rqst);
260 if (send_length != smb_buf_length + 4) { 260 rfc1002_marker = cpu_to_be32(send_length);
261 WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
262 send_length, smb_buf_length);
263 return -EIO;
264 }
265
266 if (n_vec < 2)
267 return -EIO;
268
269 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
270 dump_smb(iov[0].iov_base, iov[0].iov_len);
271 dump_smb(iov[1].iov_base, iov[1].iov_len);
272 261
273 /* cork the socket */ 262 /* cork the socket */
274 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, 263 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
275 (char *)&val, sizeof(val)); 264 (char *)&val, sizeof(val));
276 265
277 size = 0; 266 size = 0;
267 /* Generate a rfc1002 marker for SMB2+ */
268 if (server->vals->header_preamble_size == 0) {
269 struct kvec hiov = {
270 .iov_base = &rfc1002_marker,
271 .iov_len = 4
272 };
273 iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, &hiov,
274 1, 4);
275 rc = smb_send_kvec(server, &smb_msg, &sent);
276 if (rc < 0)
277 goto uncork;
278
279 total_len += sent;
280 send_length += 4;
281 }
282
283 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", send_length);
284 dump_smb(iov[0].iov_base, iov[0].iov_len);
285 dump_smb(iov[1].iov_base, iov[1].iov_len);
286
278 for (i = 0; i < n_vec; i++) 287 for (i = 0; i < n_vec; i++)
279 size += iov[i].iov_len; 288 size += iov[i].iov_len;
280 289
@@ -308,9 +317,9 @@ uncork:
308 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, 317 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
309 (char *)&val, sizeof(val)); 318 (char *)&val, sizeof(val));
310 319
311 if ((total_len > 0) && (total_len != smb_buf_length + 4)) { 320 if ((total_len > 0) && (total_len != send_length)) {
312 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n", 321 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
313 smb_buf_length + 4, total_len); 322 send_length, total_len);
314 /* 323 /*
315 * If we have only sent part of an SMB then the next SMB could 324 * If we have only sent part of an SMB then the next SMB could
316 * be taken as the remainder of this one. We need to kill the 325 * be taken as the remainder of this one. We need to kill the
@@ -730,7 +739,6 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
730 * to the same server. We may make this configurable later or 739 * to the same server. We may make this configurable later or
731 * use ses->maxReq. 740 * use ses->maxReq.
732 */ 741 */
733
734 rc = wait_for_free_request(ses->server, timeout, optype); 742 rc = wait_for_free_request(ses->server, timeout, optype);
735 if (rc) 743 if (rc)
736 return rc; 744 return rc;
@@ -766,8 +774,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
766 774
767#ifdef CONFIG_CIFS_SMB311 775#ifdef CONFIG_CIFS_SMB311
768 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) 776 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
769 smb311_update_preauth_hash(ses, rqst->rq_iov+1, 777 smb311_update_preauth_hash(ses, rqst->rq_iov,
770 rqst->rq_nvec-1); 778 rqst->rq_nvec);
771#endif 779#endif
772 780
773 if (timeout == CIFS_ASYNC_OP) 781 if (timeout == CIFS_ASYNC_OP)
@@ -812,8 +820,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
812#ifdef CONFIG_CIFS_SMB311 820#ifdef CONFIG_CIFS_SMB311
813 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { 821 if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
814 struct kvec iov = { 822 struct kvec iov = {
815 .iov_base = buf, 823 .iov_base = resp_iov->iov_base,
816 .iov_len = midQ->resp_buf_size 824 .iov_len = resp_iov->iov_len
817 }; 825 };
818 smb311_update_preauth_hash(ses, &iov, 1); 826 smb311_update_preauth_hash(ses, &iov, 1);
819 } 827 }
@@ -879,39 +887,13 @@ smb2_send_recv(const unsigned int xid, struct cifs_ses *ses,
879 const int flags, struct kvec *resp_iov) 887 const int flags, struct kvec *resp_iov)
880{ 888{
881 struct smb_rqst rqst; 889 struct smb_rqst rqst;
882 struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
883 int rc; 890 int rc;
884 int i;
885 __u32 count;
886 __be32 rfc1002_marker;
887
888 if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
889 new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
890 GFP_KERNEL);
891 if (!new_iov)
892 return -ENOMEM;
893 } else
894 new_iov = s_iov;
895
896 /* 1st iov is an RFC1002 Session Message length */
897 memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
898
899 count = 0;
900 for (i = 1; i < n_vec + 1; i++)
901 count += new_iov[i].iov_len;
902
903 rfc1002_marker = cpu_to_be32(count);
904
905 new_iov[0].iov_base = &rfc1002_marker;
906 new_iov[0].iov_len = 4;
907 891
908 memset(&rqst, 0, sizeof(struct smb_rqst)); 892 memset(&rqst, 0, sizeof(struct smb_rqst));
909 rqst.rq_iov = new_iov; 893 rqst.rq_iov = iov;
910 rqst.rq_nvec = n_vec + 1; 894 rqst.rq_nvec = n_vec;
911 895
912 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); 896 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
913 if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
914 kfree(new_iov);
915 return rc; 897 return rc;
916} 898}
917 899