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)); |
