diff options
-rw-r--r-- | fs/cifs/CHANGES | 6 | ||||
-rw-r--r-- | fs/cifs/connect.c | 4 | ||||
-rw-r--r-- | fs/cifs/misc.c | 27 |
3 files changed, 24 insertions, 13 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index a9cf779cf35e..cf846c73bc69 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -2,7 +2,11 @@ Version 1.41 | |||
2 | ------------ | 2 | ------------ |
3 | Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can | 3 | Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can |
4 | configure stronger authentication. Fix sfu symlinks so they can | 4 | configure stronger authentication. Fix sfu symlinks so they can |
5 | be followed (not just recognized). | 5 | be followed (not just recognized). Fix wraparound of bcc on |
6 | read responses when buffer size over 64K and also fix wrap of | ||
7 | max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in | ||
8 | cifs_user_read and cifs_readpages (when EAGAIN on send of smb | ||
9 | on socket is returned over and over) | ||
6 | 10 | ||
7 | Version 1.40 | 11 | Version 1.40 |
8 | ------------ | 12 | ------------ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 16535b510a96..cf4bcf3a45e6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
564 | 564 | ||
565 | 565 | ||
566 | dump_smb(smb_buffer, length); | 566 | dump_smb(smb_buffer, length); |
567 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { | 567 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { |
568 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); | 568 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); |
569 | continue; | 569 | continue; |
570 | } | 570 | } |
@@ -2278,6 +2278,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2278 | smb_buffer->Mid = GetNextMid(ses->server); | 2278 | smb_buffer->Mid = GetNextMid(ses->server); |
2279 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2279 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2280 | pSMB->req.AndXCommand = 0xFF; | 2280 | pSMB->req.AndXCommand = 0xFF; |
2281 | if(ses->server->maxBuf > 64*1024) | ||
2282 | ses->server->maxBuf = (64*1023); | ||
2281 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 2283 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
2282 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 2284 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
2283 | 2285 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 0f3ebad09d3e..988b8cec8568 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -421,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
421 | { | 421 | { |
422 | __u32 len = smb->smb_buf_length; | 422 | __u32 len = smb->smb_buf_length; |
423 | __u32 clc_len; /* calculated length */ | 423 | __u32 clc_len; /* calculated length */ |
424 | cFYI(0, | 424 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); |
425 | ("Entering checkSMB with Length: %x, smb_buf_length: %x", | ||
426 | length, len)); | ||
427 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || | 425 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || |
428 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { | 426 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { |
429 | if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { | 427 | if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { |
@@ -435,22 +433,29 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
435 | } else { | 433 | } else { |
436 | cERROR(1, ("Length less than smb header size")); | 434 | cERROR(1, ("Length less than smb header size")); |
437 | } | 435 | } |
438 | |||
439 | } | 436 | } |
440 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 437 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) |
441 | cERROR(1, | 438 | cERROR(1, ("smb length greater than MaxBufSize, mid=%d", |
442 | ("smb_buf_length greater than MaxBufSize")); | 439 | smb->Mid)); |
443 | cERROR(1, | ||
444 | ("bad smb detected. Illegal length. mid=%d", | ||
445 | smb->Mid)); | ||
446 | return 1; | 440 | return 1; |
447 | } | 441 | } |
448 | 442 | ||
449 | if (checkSMBhdr(smb, mid)) | 443 | if (checkSMBhdr(smb, mid)) |
450 | return 1; | 444 | return 1; |
451 | clc_len = smbCalcSize_LE(smb); | 445 | clc_len = smbCalcSize_LE(smb); |
452 | if ((4 + len != clc_len) | 446 | |
453 | || (4 + len != (unsigned int)length)) { | 447 | if(4 + len != (unsigned int)length) { |
448 | cERROR(1, ("Length read does not match RFC1001 length %d",len)); | ||
449 | return 1; | ||
450 | } | ||
451 | |||
452 | if (4 + len != clc_len) { | ||
453 | /* check if bcc wrapped around for large read responses */ | ||
454 | if((len > 64 * 1024) && (len > clc_len)) { | ||
455 | /* check if lengths match mod 64K */ | ||
456 | if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) | ||
457 | return 0; /* bcc wrapped */ | ||
458 | } | ||
454 | cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", | 459 | cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", |
455 | clc_len, 4 + len)); | 460 | clc_len, 4 + len)); |
456 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); | 461 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); |