diff options
| author | Ronnie Sahlberg <lsahlber@redhat.com> | 2018-06-11 18:00:58 -0400 |
|---|---|---|
| committer | Steve French <stfrench@microsoft.com> | 2018-06-15 03:38:08 -0400 |
| commit | c713c8770fa5bfbeaac088cc7b959c7a6ba79f93 (patch) | |
| tree | 76b49e4511ff8b37777552aa150caae3033ce77c | |
| parent | d409014e4feeab486fb36b350abfc4c94de8be37 (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.c | 23 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
| -rw-r--r-- | fs/cifs/smb2ops.c | 71 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 38 | ||||
| -rw-r--r-- | fs/cifs/smb2transport.c | 18 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 82 |
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 | ||
| 39 | int __cifs_calc_signature(struct smb_rqst *rqst, | 39 | int __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); |
| 547 | int __cifs_calc_signature(struct smb_rqst *rqst, int start, | 547 | int __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); |
| 550 | enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, | 550 | enum 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 | */ |
| 2194 | static struct scatterlist * | 2193 | static struct scatterlist * |
| 2195 | init_sg(struct smb_rqst *rqst, u8 *sign) | 2194 | init_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 | */ |
| 2250 | static int | 2248 | static 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 | */ | ||
| 2346 | static int | 2340 | static int |
| 2347 | smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, | 2341 | smb3_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 | ||
