aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-01-20 13:36:51 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-20 16:46:29 -0500
commit690c522fa5a62825af880775e3ef1e55755667b2 (patch)
treeff953bba1050b54cc9be452a599ac1faf580c3b7
parentaae62fdb6b9a6605abdea7370c4a0e005e6c1cd7 (diff)
cifs: use get/put_unaligned functions to access ByteCount
It's possible that when we access the ByteCount that the alignment will be off. Most CPUs deal with that transparently, but there's usually some performance impact. Some CPUs raise an exception on unaligned accesses. Fix this by accessing the byte count using the get_unaligned and put_unaligned inlined functions. While we're at it, fix the types of some of the variables that end up getting returns from these functions. Acked-by: Pavel Shilovsky <piastryyy@gmail.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cifspdu.h47
-rw-r--r--fs/cifs/cifssmb.c14
-rw-r--r--fs/cifs/connect.c10
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/sess.c13
-rw-r--r--fs/cifs/transport.c9
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 */
439static inline __u16
440get_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 */
448static inline __u16
449get_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 */
457static inline void
458put_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 */
466static inline void
467put_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
365int 361int
366CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) 362CIFSSMBNegotiate(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
916smbCalcSize(struct smb_hdr *ptr) 916smbCalcSize(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
922unsigned int 922unsigned int
923smbCalcSize_LE(struct smb_hdr *ptr) 923smbCalcSize_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
279static void 279static void
280decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, 280decode_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
326static int decode_ascii_ssetup(char **pbcc_area, int bleft, 326static 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
982out: 981out:
983 delete_mid(midQ); 982 delete_mid(midQ);