aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-02-24 06:15:11 +0000
committerSteve French <sfrench@us.ibm.com>2006-02-24 06:15:11 +0000
commit184ed2110ae6bfdb8dc91085149f04f2f4d2169e (patch)
treee36ae13694fb922cc2244ef6fffad7f93a6c90e0
parent5d2f248a5f3acac4b763439327c92091be7abb1c (diff)
downloadlinux-184ed2110ae6bfdb8dc91085149f04f2f4d2169e.tar.gz
[CIFS] Fix large (ie over 64K for MaxCIFSBufSize) buffer case for wrapping
bcc on read response and for wrapping sessionsetup maxbufsize field Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/CHANGES6
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/misc.c27
3 files changed, 24 insertions, 13 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a9cf779cf35ea..cf846c73bc697 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -2,7 +2,11 @@ Version 1.41
------------
Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can
configure stronger authentication. Fix sfu symlinks so they can
-be followed (not just recognized).
+be followed (not just recognized). Fix wraparound of bcc on
+read responses when buffer size over 64K and also fix wrap of
+max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in
+cifs_user_read and cifs_readpages (when EAGAIN on send of smb
+on socket is returned over and over)
Version 1.40
------------
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 16535b510a968..cf4bcf3a45e68 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
dump_smb(smb_buffer, length);
- if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
+ if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
continue;
}
@@ -2278,6 +2278,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF;
+ if(ses->server->maxBuf > 64*1024)
+ ses->server->maxBuf = (64*1023);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 0f3ebad09d3ef..988b8cec85685 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -421,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
{
__u32 len = smb->smb_buf_length;
__u32 clc_len; /* calculated length */
- cFYI(0,
- ("Entering checkSMB with Length: %x, smb_buf_length: %x",
- length, len));
+ cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
@@ -435,22 +433,29 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
} else {
cERROR(1, ("Length less than smb header size"));
}
-
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
- cERROR(1,
- ("smb_buf_length greater than MaxBufSize"));
- cERROR(1,
- ("bad smb detected. Illegal length. mid=%d",
- smb->Mid));
+ cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+ smb->Mid));
return 1;
}
if (checkSMBhdr(smb, mid))
return 1;
clc_len = smbCalcSize_LE(smb);
- if ((4 + len != clc_len)
- || (4 + len != (unsigned int)length)) {
+
+ if(4 + len != (unsigned int)length) {
+ cERROR(1, ("Length read does not match RFC1001 length %d",len));
+ return 1;
+ }
+
+ if (4 + len != clc_len) {
+ /* check if bcc wrapped around for large read responses */
+ if((len > 64 * 1024) && (len > clc_len)) {
+ /* check if lengths match mod 64K */
+ if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
+ return 0; /* bcc wrapped */
+ }
cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
clc_len, 4 + len));
cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));