diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-10-11 06:41:32 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2011-10-13 00:41:36 -0400 |
commit | 376b43f41c8b9315f7efdf085d214b6024337381 (patch) | |
tree | 0a5e1959a71d2b645faf731ae062c7a27fdc8421 /fs/cifs/misc.c | |
parent | c974befa402b5eb2ed115b3083b5a46a4be85a9f (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>
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r-- | fs/cifs/misc.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 7c1693392598..4a1801b3195f 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 | ||
422 | int | 422 | int |
423 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | 423 | checkSMB(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; |