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); |
