aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/misc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-10-13 11:09:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-13 11:09:29 -0400
commit12e36b2f41b6cbc67386fcb9c59c32a3e2033905 (patch)
treeec1794bae2f96eef6cc2afb2fa5c48e6fd346316 /fs/cifs/misc.c
parent1baaf0b424fe611a99cf3e2e59e84df0561d679a (diff)
parent1a4e15a04ec69cb3552f4120079f5472377df5f7 (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.c44
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
392int 392static int
393checkSMBhdr(struct smb_hdr *smb, __u16 mid) 393checkSMBhdr(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
420int 420int
421checkSMB(struct smb_hdr *smb, __u16 mid, int length) 421checkSMB(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 }