diff options
-rw-r--r-- | fs/cifs/cifspdu.h | 47 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 14 | ||||
-rw-r--r-- | fs/cifs/connect.c | 10 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
-rw-r--r-- | fs/cifs/sess.c | 13 | ||||
-rw-r--r-- | fs/cifs/transport.c | 9 |
6 files changed, 65 insertions, 32 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index ea205b4fcad2..b5c8cc5d7a7f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define _CIFSPDU_H | 23 | #define _CIFSPDU_H |
24 | 24 | ||
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/unaligned.h> | ||
26 | #include "smbfsctl.h" | 27 | #include "smbfsctl.h" |
27 | 28 | ||
28 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 29 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
@@ -426,11 +427,49 @@ struct smb_hdr { | |||
426 | __u16 Mid; | 427 | __u16 Mid; |
427 | __u8 WordCount; | 428 | __u8 WordCount; |
428 | } __attribute__((packed)); | 429 | } __attribute__((packed)); |
429 | /* given a pointer to an smb_hdr retrieve the value of byte count */ | 430 | |
430 | #define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 431 | /* given a pointer to an smb_hdr retrieve a char pointer to the byte count */ |
431 | #define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 432 | #define BCC(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + \ |
433 | (2 * (smb_var)->WordCount)) | ||
434 | |||
432 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 435 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
433 | #define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2) | 436 | #define pByteArea(smb_var) (BCC(smb_var) + 2) |
437 | |||
438 | /* get the converted ByteCount for a SMB packet and return it */ | ||
439 | static inline __u16 | ||
440 | get_bcc(struct smb_hdr *hdr) | ||
441 | { | ||
442 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
443 | |||
444 | return get_unaligned(bc_ptr); | ||
445 | } | ||
446 | |||
447 | /* get the unconverted ByteCount for a SMB packet and return it */ | ||
448 | static inline __u16 | ||
449 | get_bcc_le(struct smb_hdr *hdr) | ||
450 | { | ||
451 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
452 | |||
453 | return get_unaligned_le16(bc_ptr); | ||
454 | } | ||
455 | |||
456 | /* set the ByteCount for a SMB packet in host-byte order */ | ||
457 | static inline void | ||
458 | put_bcc(__u16 count, struct smb_hdr *hdr) | ||
459 | { | ||
460 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
461 | |||
462 | put_unaligned(count, bc_ptr); | ||
463 | } | ||
464 | |||
465 | /* set the ByteCount for a SMB packet in little-endian */ | ||
466 | static inline void | ||
467 | put_bcc_le(__u16 count, struct smb_hdr *hdr) | ||
468 | { | ||
469 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
470 | |||
471 | put_unaligned_le16(count, bc_ptr); | ||
472 | } | ||
434 | 473 | ||
435 | /* | 474 | /* |
436 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) | 475 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 5b1f6637f161..39cec0d9cd1b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -333,7 +333,6 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
333 | { | 333 | { |
334 | int rc = -EINVAL; | 334 | int rc = -EINVAL; |
335 | int total_size; | 335 | int total_size; |
336 | char *pBCC; | ||
337 | 336 | ||
338 | /* check for plausible wct, bcc and t2 data and parm sizes */ | 337 | /* check for plausible wct, bcc and t2 data and parm sizes */ |
339 | /* check for parm and data offset going beyond end of smb */ | 338 | /* check for parm and data offset going beyond end of smb */ |
@@ -346,13 +345,9 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
346 | if (total_size < 512) { | 345 | if (total_size < 512) { |
347 | total_size += | 346 | total_size += |
348 | le16_to_cpu(pSMB->t2_rsp.DataCount); | 347 | le16_to_cpu(pSMB->t2_rsp.DataCount); |
349 | /* BCC le converted in SendReceive */ | 348 | if (total_size <= get_bcc(&pSMB->hdr) && |
350 | pBCC = (pSMB->hdr.WordCount * 2) + | 349 | total_size < |
351 | sizeof(struct smb_hdr) + | 350 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
352 | (char *)pSMB; | ||
353 | if ((total_size <= (*(u16 *)pBCC)) && | ||
354 | (total_size < | ||
355 | CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { | ||
356 | return 0; | 351 | return 0; |
357 | } | 352 | } |
358 | } | 353 | } |
@@ -362,6 +357,7 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
362 | sizeof(struct smb_t2_rsp) + 16); | 357 | sizeof(struct smb_t2_rsp) + 16); |
363 | return rc; | 358 | return rc; |
364 | } | 359 | } |
360 | |||
365 | int | 361 | int |
366 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 362 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
367 | { | 363 | { |
@@ -5609,7 +5605,7 @@ QAllEAsRetry: | |||
5609 | } | 5605 | } |
5610 | 5606 | ||
5611 | /* make sure list_len doesn't go past end of SMB */ | 5607 | /* make sure list_len doesn't go past end of SMB */ |
5612 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); | 5608 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr); |
5613 | if ((char *)ea_response_data + list_len > end_of_smb) { | 5609 | if ((char *)ea_response_data + list_len > end_of_smb) { |
5614 | cFYI(1, "EA list appears to go beyond SMB"); | 5610 | cFYI(1, "EA list appears to go beyond SMB"); |
5615 | rc = -EIO; | 5611 | rc = -EIO; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8d4657596301..ca20e813275d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -318,9 +318,9 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
318 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 318 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); |
319 | total_in_buf += total_in_buf2; | 319 | total_in_buf += total_in_buf2; |
320 | pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); | 320 | pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); |
321 | byte_count = le16_to_cpu(BCC_LE(pTargetSMB)); | 321 | byte_count = get_bcc_le(pTargetSMB); |
322 | byte_count += total_in_buf2; | 322 | byte_count += total_in_buf2; |
323 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 323 | put_bcc_le(byte_count, pTargetSMB); |
324 | 324 | ||
325 | byte_count = pTargetSMB->smb_buf_length; | 325 | byte_count = pTargetSMB->smb_buf_length; |
326 | byte_count += total_in_buf2; | 326 | byte_count += total_in_buf2; |
@@ -2937,8 +2937,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2937 | TCONX_RSP *pSMBr; | 2937 | TCONX_RSP *pSMBr; |
2938 | unsigned char *bcc_ptr; | 2938 | unsigned char *bcc_ptr; |
2939 | int rc = 0; | 2939 | int rc = 0; |
2940 | int length, bytes_left; | 2940 | int length; |
2941 | __u16 count; | 2941 | __u16 bytes_left, count; |
2942 | 2942 | ||
2943 | if (ses == NULL) | 2943 | if (ses == NULL) |
2944 | return -EIO; | 2944 | return -EIO; |
@@ -3032,7 +3032,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3032 | tcon->need_reconnect = false; | 3032 | tcon->need_reconnect = false; |
3033 | tcon->tid = smb_buffer_response->Tid; | 3033 | tcon->tid = smb_buffer_response->Tid; |
3034 | bcc_ptr = pByteArea(smb_buffer_response); | 3034 | bcc_ptr = pByteArea(smb_buffer_response); |
3035 | bytes_left = BCC(smb_buffer_response); | 3035 | bytes_left = get_bcc(smb_buffer_response); |
3036 | length = strnlen(bcc_ptr, bytes_left - 2); | 3036 | length = strnlen(bcc_ptr, bytes_left - 2); |
3037 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) | 3037 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) |
3038 | is_unicode = true; | 3038 | is_unicode = true; |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 6783ce6cdc89..8d9189f64477 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -916,14 +916,14 @@ unsigned int | |||
916 | smbCalcSize(struct smb_hdr *ptr) | 916 | smbCalcSize(struct smb_hdr *ptr) |
917 | { | 917 | { |
918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
919 | 2 /* size of the bcc field */ + BCC(ptr)); | 919 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
920 | } | 920 | } |
921 | 921 | ||
922 | unsigned int | 922 | unsigned int |
923 | smbCalcSize_LE(struct smb_hdr *ptr) | 923 | smbCalcSize_LE(struct smb_hdr *ptr) |
924 | { | 924 | { |
925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
926 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); | 926 | 2 /* size of the bcc field */ + get_bcc_le(ptr)); |
927 | } | 927 | } |
928 | 928 | ||
929 | /* The following are taken from fs/ntfs/util.c */ | 929 | /* The following are taken from fs/ntfs/util.c */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 1cffd82c4f13..1adc9625a344 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -277,7 +277,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | |||
277 | } | 277 | } |
278 | 278 | ||
279 | static void | 279 | static void |
280 | decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | 280 | decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, |
281 | const struct nls_table *nls_cp) | 281 | const struct nls_table *nls_cp) |
282 | { | 282 | { |
283 | int len; | 283 | int len; |
@@ -323,7 +323,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | |||
323 | return; | 323 | return; |
324 | } | 324 | } |
325 | 325 | ||
326 | static int decode_ascii_ssetup(char **pbcc_area, int bleft, | 326 | static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, |
327 | struct cifsSesInfo *ses, | 327 | struct cifsSesInfo *ses, |
328 | const struct nls_table *nls_cp) | 328 | const struct nls_table *nls_cp) |
329 | { | 329 | { |
@@ -575,12 +575,11 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
575 | char *str_area; | 575 | char *str_area; |
576 | SESSION_SETUP_ANDX *pSMB; | 576 | SESSION_SETUP_ANDX *pSMB; |
577 | __u32 capabilities; | 577 | __u32 capabilities; |
578 | int count; | 578 | __u16 count; |
579 | int resp_buf_type; | 579 | int resp_buf_type; |
580 | struct kvec iov[3]; | 580 | struct kvec iov[3]; |
581 | enum securityEnum type; | 581 | enum securityEnum type; |
582 | __u16 action; | 582 | __u16 action, bytes_remaining; |
583 | int bytes_remaining; | ||
584 | struct key *spnego_key = NULL; | 583 | struct key *spnego_key = NULL; |
585 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 584 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
586 | u16 blob_len; | 585 | u16 blob_len; |
@@ -876,7 +875,7 @@ ssetup_ntlmssp_authenticate: | |||
876 | count = iov[1].iov_len + iov[2].iov_len; | 875 | count = iov[1].iov_len + iov[2].iov_len; |
877 | smb_buf->smb_buf_length += count; | 876 | smb_buf->smb_buf_length += count; |
878 | 877 | ||
879 | BCC_LE(smb_buf) = cpu_to_le16(count); | 878 | put_bcc_le(count, smb_buf); |
880 | 879 | ||
881 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, | 880 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
882 | CIFS_LOG_ERROR); | 881 | CIFS_LOG_ERROR); |
@@ -910,7 +909,7 @@ ssetup_ntlmssp_authenticate: | |||
910 | cFYI(1, "UID = %d ", ses->Suid); | 909 | cFYI(1, "UID = %d ", ses->Suid); |
911 | /* response can have either 3 or 4 word count - Samba sends 3 */ | 910 | /* response can have either 3 or 4 word count - Samba sends 3 */ |
912 | /* and lanman response is 3 */ | 911 | /* and lanman response is 3 */ |
913 | bytes_remaining = BCC(smb_buf); | 912 | bytes_remaining = get_bcc(smb_buf); |
914 | bcc_ptr = pByteArea(smb_buf); | 913 | bcc_ptr = pByteArea(smb_buf); |
915 | 914 | ||
916 | if (smb_buf->WordCount == 4) { | 915 | if (smb_buf->WordCount == 4) { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index c8e2808cd5e6..c1ccca1a933f 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -484,7 +484,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
484 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; | 484 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; |
485 | in_buf->Command = SMB_COM_NT_CANCEL; | 485 | in_buf->Command = SMB_COM_NT_CANCEL; |
486 | in_buf->WordCount = 0; | 486 | in_buf->WordCount = 0; |
487 | BCC_LE(in_buf) = 0; | 487 | put_bcc_le(0, in_buf); |
488 | 488 | ||
489 | mutex_lock(&server->srv_mutex); | 489 | mutex_lock(&server->srv_mutex); |
490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | 490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); |
@@ -632,8 +632,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
632 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 632 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
633 | /* do not count RFC1001 header */ + | 633 | /* do not count RFC1001 header */ + |
634 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | 634 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) |
635 | BCC(midQ->resp_buf) = | 635 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
636 | le16_to_cpu(BCC_LE(midQ->resp_buf)); | ||
637 | if ((flags & CIFS_NO_RESP) == 0) | 636 | if ((flags & CIFS_NO_RESP) == 0) |
638 | midQ->resp_buf = NULL; /* mark it so buf will | 637 | midQ->resp_buf = NULL; /* mark it so buf will |
639 | not be freed by | 638 | not be freed by |
@@ -776,7 +775,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
776 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 775 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
777 | /* do not count RFC1001 header */ + | 776 | /* do not count RFC1001 header */ + |
778 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 777 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
779 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 778 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
780 | } else { | 779 | } else { |
781 | rc = -EIO; | 780 | rc = -EIO; |
782 | cERROR(1, "Bad MID state?"); | 781 | cERROR(1, "Bad MID state?"); |
@@ -977,7 +976,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
977 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 976 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
978 | /* do not count RFC1001 header */ + | 977 | /* do not count RFC1001 header */ + |
979 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 978 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
980 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 979 | put_bcc(get_bcc_le(out_buf), out_buf); |
981 | 980 | ||
982 | out: | 981 | out: |
983 | delete_mid(midQ); | 982 | delete_mid(midQ); |