diff options
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r-- | fs/cifs/misc.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 34a06692e4f..812c6bb0fe3 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/misc.c | 2 | * fs/cifs/misc.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2002,2004 | 4 | * Copyright (C) International Business Machines Corp., 2002,2005 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -161,6 +161,9 @@ cifs_buf_get(void) | |||
161 | if (ret_buf) { | 161 | if (ret_buf) { |
162 | memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); | 162 | memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); |
163 | atomic_inc(&bufAllocCount); | 163 | atomic_inc(&bufAllocCount); |
164 | #ifdef CONFIG_CIFS_STATS2 | ||
165 | atomic_inc(&totBufAllocCount); | ||
166 | #endif /* CONFIG_CIFS_STATS2 */ | ||
164 | } | 167 | } |
165 | 168 | ||
166 | return ret_buf; | 169 | return ret_buf; |
@@ -195,6 +198,10 @@ cifs_small_buf_get(void) | |||
195 | /* No need to clear memory here, cleared in header assemble */ | 198 | /* No need to clear memory here, cleared in header assemble */ |
196 | /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ | 199 | /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ |
197 | atomic_inc(&smBufAllocCount); | 200 | atomic_inc(&smBufAllocCount); |
201 | #ifdef CONFIG_CIFS_STATS2 | ||
202 | atomic_inc(&totSmBufAllocCount); | ||
203 | #endif /* CONFIG_CIFS_STATS2 */ | ||
204 | |||
198 | } | 205 | } |
199 | return ret_buf; | 206 | return ret_buf; |
200 | } | 207 | } |
@@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
292 | struct cifsSesInfo * ses; | 299 | struct cifsSesInfo * ses; |
293 | char *temp = (char *) buffer; | 300 | char *temp = (char *) buffer; |
294 | 301 | ||
295 | memset(temp,0,MAX_CIFS_HDR_SIZE); | 302 | memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */ |
296 | 303 | ||
297 | buffer->smb_buf_length = | 304 | buffer->smb_buf_length = |
298 | (2 * word_count) + sizeof (struct smb_hdr) - | 305 | (2 * word_count) + sizeof (struct smb_hdr) - |
@@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
348 | /* BB Add support for establishing new tCon and SMB Session */ | 355 | /* BB Add support for establishing new tCon and SMB Session */ |
349 | /* with userid/password pairs found on the smb session */ | 356 | /* with userid/password pairs found on the smb session */ |
350 | /* for other target tcp/ip addresses BB */ | 357 | /* for other target tcp/ip addresses BB */ |
351 | if(current->uid != treeCon->ses->linux_uid) { | 358 | if(current->fsuid != treeCon->ses->linux_uid) { |
352 | cFYI(1,("Multiuser mode and UID did not match tcon uid ")); | 359 | cFYI(1,("Multiuser mode and UID did not match tcon uid")); |
353 | read_lock(&GlobalSMBSeslock); | 360 | read_lock(&GlobalSMBSeslock); |
354 | list_for_each(temp_item, &GlobalSMBSessionList) { | 361 | list_for_each(temp_item, &GlobalSMBSessionList) { |
355 | ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); | 362 | ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); |
356 | if(ses->linux_uid == current->uid) { | 363 | if(ses->linux_uid == current->fsuid) { |
357 | if(ses->server == treeCon->ses->server) { | 364 | if(ses->server == treeCon->ses->server) { |
358 | cFYI(1,("found matching uid substitute right smb_uid")); | 365 | cFYI(1,("found matching uid substitute right smb_uid")); |
359 | buffer->Uid = ses->Suid; | 366 | buffer->Uid = ses->Suid; |
@@ -397,12 +404,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) | |||
397 | if(smb->Command == SMB_COM_LOCKING_ANDX) | 404 | if(smb->Command == SMB_COM_LOCKING_ANDX) |
398 | return 0; | 405 | return 0; |
399 | else | 406 | else |
400 | cERROR(1, ("Rcvd Request not response ")); | 407 | cERROR(1, ("Rcvd Request not response")); |
401 | } | 408 | } |
402 | } else { /* bad signature or mid */ | 409 | } else { /* bad signature or mid */ |
403 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) | 410 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) |
404 | cERROR(1, | 411 | cERROR(1, |
405 | ("Bad protocol string signature header %x ", | 412 | ("Bad protocol string signature header %x", |
406 | *(unsigned int *) smb->Protocol)); | 413 | *(unsigned int *) smb->Protocol)); |
407 | if (mid != smb->Mid) | 414 | if (mid != smb->Mid) |
408 | cERROR(1, ("Mids do not match")); | 415 | cERROR(1, ("Mids do not match")); |
@@ -417,7 +424,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
417 | __u32 len = smb->smb_buf_length; | 424 | __u32 len = smb->smb_buf_length; |
418 | __u32 clc_len; /* calculated length */ | 425 | __u32 clc_len; /* calculated length */ |
419 | cFYI(0, | 426 | cFYI(0, |
420 | ("Entering checkSMB with Length: %x, smb_buf_length: %x ", | 427 | ("Entering checkSMB with Length: %x, smb_buf_length: %x", |
421 | length, len)); | 428 | length, len)); |
422 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || | 429 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || |
423 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { | 430 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { |
@@ -451,9 +458,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
451 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); | 458 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); |
452 | /* Windows XP can return a few bytes too much, presumably | 459 | /* Windows XP can return a few bytes too much, presumably |
453 | an illegal pad, at the end of byte range lock responses | 460 | an illegal pad, at the end of byte range lock responses |
454 | so we allow for up to eight byte pad, as long as actual | 461 | so we allow for that three byte pad, as long as actual |
455 | received length is as long or longer than calculated length */ | 462 | received length is as long or longer than calculated length */ |
456 | if((4+len > clc_len) && (len <= clc_len + 3)) | 463 | /* We have now had to extend this more, since there is a |
464 | case in which it needs to be bigger still to handle a | ||
465 | malformed response to transact2 findfirst from WinXP when | ||
466 | access denied is returned and thus bcc and wct are zero | ||
467 | but server says length is 0x21 bytes too long as if the server | ||
468 | forget to reset the smb rfc1001 length when it reset the | ||
469 | wct and bcc to minimum size and drop the t2 parms and data */ | ||
470 | if((4+len > clc_len) && (len <= clc_len + 512)) | ||
457 | return 0; | 471 | return 0; |
458 | else | 472 | else |
459 | return 1; | 473 | return 1; |
@@ -678,7 +692,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | |||
678 | __u16 temp; | 692 | __u16 temp; |
679 | 693 | ||
680 | if(!mapChars) | 694 | if(!mapChars) |
681 | return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); | 695 | return cifs_strtoUCS(target, source, PATH_MAX, cp); |
682 | 696 | ||
683 | for(i = 0, j = 0; i < maxlen; j++) { | 697 | for(i = 0, j = 0; i < maxlen; j++) { |
684 | src_char = source[i]; | 698 | src_char = source[i]; |