diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-13 11:09:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-13 11:09:29 -0400 |
commit | 12e36b2f41b6cbc67386fcb9c59c32a3e2033905 (patch) | |
tree | ec1794bae2f96eef6cc2afb2fa5c48e6fd346316 /fs/cifs/misc.c | |
parent | 1baaf0b424fe611a99cf3e2e59e84df0561d679a (diff) | |
parent | 1a4e15a04ec69cb3552f4120079f5472377df5f7 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (27 commits)
[CIFS] Missing flags2 for DFS
[CIFS] Workaround incomplete byte length returned by some
[CIFS] cifs Kconfig: don't select CONNECTOR
[CIFS] Level 1 QPathInfo needed for proper OS2 support
[CIFS] fix typo in previous patch
[CIFS] Fix old DOS time conversion to handle timezone
[CIFS] Do not need to adjust for Jan/Feb for leap day
[CIFS] Fix leaps year calculation for years after 2100
[CIFS] readdir (ffirst) enablement of accurate timestamps from legacy servers
[CIFS] Fix compiler warning with previous patch
[CIFS] Fix typo
[CIFS] Allow for 15 minute TZs (e.g. Nepal) and be more explicit about
[CIFS] Fix readdir of large directories for backlevel servers
[CIFS] Allow LANMAN21 support even in both POSIX non-POSIX path
[CIFS] Make use of newer QFSInfo dependent on capability bit instead of
[CIFS] Do not send newer QFSInfo to legacy servers which can not support it
[CIFS] Fix typo in name of new cifs_show_stats
[CIFS] Rename server time zone field
[CIFS] Handle legacy servers which return undefined time zone
[CIFS] CIFS support for /proc/<pid>/mountstats part 1
...
Manual conflict resolution in fs/cifs/connect.c
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r-- | fs/cifs/misc.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 22c937e5884f..bbc9cd34b6ea 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -389,7 +389,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
389 | return; | 389 | return; |
390 | } | 390 | } |
391 | 391 | ||
392 | int | 392 | static int |
393 | checkSMBhdr(struct smb_hdr *smb, __u16 mid) | 393 | checkSMBhdr(struct smb_hdr *smb, __u16 mid) |
394 | { | 394 | { |
395 | /* Make sure that this really is an SMB, that it is a response, | 395 | /* Make sure that this really is an SMB, that it is a response, |
@@ -418,26 +418,42 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) | |||
418 | } | 418 | } |
419 | 419 | ||
420 | int | 420 | int |
421 | checkSMB(struct smb_hdr *smb, __u16 mid, int length) | 421 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) |
422 | { | 422 | { |
423 | __u32 len = smb->smb_buf_length; | 423 | __u32 len = smb->smb_buf_length; |
424 | __u32 clc_len; /* calculated length */ | 424 | __u32 clc_len; /* calculated length */ |
425 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); | 425 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); |
426 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || | 426 | |
427 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { | 427 | if (length < 2 + sizeof (struct smb_hdr)) { |
428 | if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { | 428 | if ((length >= sizeof (struct smb_hdr) - 1) |
429 | if (((unsigned int)length >= | ||
430 | sizeof (struct smb_hdr) - 1) | ||
431 | && (smb->Status.CifsError != 0)) { | 429 | && (smb->Status.CifsError != 0)) { |
432 | smb->WordCount = 0; | 430 | smb->WordCount = 0; |
433 | /* some error cases do not return wct and bcc */ | 431 | /* some error cases do not return wct and bcc */ |
432 | return 0; | ||
433 | } else if ((length == sizeof(struct smb_hdr) + 1) && | ||
434 | (smb->WordCount == 0)) { | ||
435 | char * tmp = (char *)smb; | ||
436 | /* Need to work around a bug in two servers here */ | ||
437 | /* First, check if the part of bcc they sent was zero */ | ||
438 | if (tmp[sizeof(struct smb_hdr)] == 0) { | ||
439 | /* some servers return only half of bcc | ||
440 | * on simple responses (wct, bcc both zero) | ||
441 | * in particular have seen this on | ||
442 | * ulogoffX and FindClose. This leaves | ||
443 | * one byte of bcc potentially unitialized | ||
444 | */ | ||
445 | /* zero rest of bcc */ | ||
446 | tmp[sizeof(struct smb_hdr)+1] = 0; | ||
434 | return 0; | 447 | return 0; |
435 | } else { | ||
436 | cERROR(1, ("Length less than smb header size")); | ||
437 | } | 448 | } |
449 | cERROR(1,("rcvd invalid byte count (bcc)")); | ||
450 | } else { | ||
451 | cERROR(1, ("Length less than smb header size")); | ||
438 | } | 452 | } |
439 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 453 | return 1; |
440 | cERROR(1, ("smb length greater than MaxBufSize, mid=%d", | 454 | } |
455 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | ||
456 | cERROR(1, ("smb length greater than MaxBufSize, mid=%d", | ||
441 | smb->Mid)); | 457 | smb->Mid)); |
442 | return 1; | 458 | return 1; |
443 | } | 459 | } |
@@ -446,7 +462,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
446 | return 1; | 462 | return 1; |
447 | clc_len = smbCalcSize_LE(smb); | 463 | clc_len = smbCalcSize_LE(smb); |
448 | 464 | ||
449 | if(4 + len != (unsigned int)length) { | 465 | if(4 + len != length) { |
450 | cERROR(1, ("Length read does not match RFC1001 length %d",len)); | 466 | cERROR(1, ("Length read does not match RFC1001 length %d",len)); |
451 | return 1; | 467 | return 1; |
452 | } | 468 | } |