aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-10-11 06:41:32 -0400
committerSteve French <smfrench@gmail.com>2011-10-13 00:41:36 -0400
commit376b43f41c8b9315f7efdf085d214b6024337381 (patch)
tree0a5e1959a71d2b645faf731ae062c7a27fdc8421
parentc974befa402b5eb2ed115b3083b5a46a4be85a9f (diff)
cifs: clean up checkSMB
The variable names in this function are so ambiguous that it's very difficult to know what it's doing. Rename them to make it a bit more clear. Also, remove a redundant length check. cifsd checks to make sure that the rfclen isn't larger than the maximum frame size when it does the receive. Finally, change checkSMB to return a real error code (-EIO) when it finds an error. That will help simplify some coming changes in the callers. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/misc.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7c169339259..4a1801b3195 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -420,19 +420,22 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
420} 420}
421 421
422int 422int
423checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) 423checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int total_read)
424{ 424{
425 __u32 len = be32_to_cpu(smb->smb_buf_length); 425 __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
426 __u32 clc_len; /* calculated length */ 426 __u32 clc_len; /* calculated length */
427 cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); 427 cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x",
428 total_read, rfclen);
428 429
429 if (length < 2 + sizeof(struct smb_hdr)) { 430 /* is this frame too small to even get to a BCC? */
430 if ((length >= sizeof(struct smb_hdr) - 1) 431 if (total_read < 2 + sizeof(struct smb_hdr)) {
432 if ((total_read >= sizeof(struct smb_hdr) - 1)
431 && (smb->Status.CifsError != 0)) { 433 && (smb->Status.CifsError != 0)) {
434 /* it's an error return */
432 smb->WordCount = 0; 435 smb->WordCount = 0;
433 /* some error cases do not return wct and bcc */ 436 /* some error cases do not return wct and bcc */
434 return 0; 437 return 0;
435 } else if ((length == sizeof(struct smb_hdr) + 1) && 438 } else if ((total_read == sizeof(struct smb_hdr) + 1) &&
436 (smb->WordCount == 0)) { 439 (smb->WordCount == 0)) {
437 char *tmp = (char *)smb; 440 char *tmp = (char *)smb;
438 /* Need to work around a bug in two servers here */ 441 /* Need to work around a bug in two servers here */
@@ -452,39 +455,35 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
452 } else { 455 } else {
453 cERROR(1, "Length less than smb header size"); 456 cERROR(1, "Length less than smb header size");
454 } 457 }
455 return 1; 458 return -EIO;
456 }
457 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
458 cERROR(1, "smb length greater than MaxBufSize, mid=%d",
459 smb->Mid);
460 return 1;
461 } 459 }
462 460
461 /* otherwise, there is enough to get to the BCC */
463 if (check_smb_hdr(smb, mid)) 462 if (check_smb_hdr(smb, mid))
464 return 1; 463 return -EIO;
465 clc_len = smbCalcSize(smb); 464 clc_len = smbCalcSize(smb);
466 465
467 if (4 + len != length) { 466 if (4 + rfclen != total_read) {
468 cERROR(1, "Length read does not match RFC1001 length %d", 467 cERROR(1, "Length read does not match RFC1001 length %d",
469 len); 468 rfclen);
470 return 1; 469 return -EIO;
471 } 470 }
472 471
473 if (4 + len != clc_len) { 472 if (4 + rfclen != clc_len) {
474 /* check if bcc wrapped around for large read responses */ 473 /* check if bcc wrapped around for large read responses */
475 if ((len > 64 * 1024) && (len > clc_len)) { 474 if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
476 /* check if lengths match mod 64K */ 475 /* check if lengths match mod 64K */
477 if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) 476 if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
478 return 0; /* bcc wrapped */ 477 return 0; /* bcc wrapped */
479 } 478 }
480 cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", 479 cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
481 clc_len, 4 + len, smb->Mid); 480 clc_len, 4 + rfclen, smb->Mid);
482 481
483 if (4 + len < clc_len) { 482 if (4 + rfclen < clc_len) {
484 cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", 483 cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
485 len, smb->Mid); 484 rfclen, smb->Mid);
486 return 1; 485 return -EIO;
487 } else if (len > clc_len + 512) { 486 } else if (rfclen > clc_len + 512) {
488 /* 487 /*
489 * Some servers (Windows XP in particular) send more 488 * Some servers (Windows XP in particular) send more
490 * data than the lengths in the SMB packet would 489 * data than the lengths in the SMB packet would
@@ -495,8 +494,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
495 * data to 512 bytes. 494 * data to 512 bytes.
496 */ 495 */
497 cERROR(1, "RFC1001 size %u more than 512 bytes larger " 496 cERROR(1, "RFC1001 size %u more than 512 bytes larger "
498 "than SMB for mid=%u", len, smb->Mid); 497 "than SMB for mid=%u", rfclen, smb->Mid);
499 return 1; 498 return -EIO;
500 } 499 }
501 } 500 }
502 return 0; 501 return 0;