diff options
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 24 | ||||
-rw-r--r-- | fs/cifs/connect.c | 38 | ||||
-rw-r--r-- | fs/cifs/misc.c | 12 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 9 | ||||
-rw-r--r-- | fs/cifs/transport.c | 4 |
8 files changed, 60 insertions, 33 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 661b45906d09..535177238020 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -4,7 +4,8 @@ Fix readdir caching when unlink removes file in current search buffer, | |||
4 | and this is followed by a rewind search to just before the deleted entry. | 4 | and this is followed by a rewind search to just before the deleted entry. |
5 | Do not attempt to set ctime unless atime and/or mtime change requested | 5 | Do not attempt to set ctime unless atime and/or mtime change requested |
6 | (most servers throw it away anyway). Fix length check of received smbs | 6 | (most servers throw it away anyway). Fix length check of received smbs |
7 | to be more accurate. | 7 | to be more accurate. Fix big endian problem with mapchars mount option, |
8 | and with a field returned by statfs. | ||
8 | 9 | ||
9 | Version 1.36 | 10 | Version 1.36 |
10 | ------------ | 11 | ------------ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 3fa37790bea2..193f06eb43f9 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -697,7 +697,7 @@ typedef struct smb_com_openx_req { | |||
697 | __le32 EndOfFile; | 697 | __le32 EndOfFile; |
698 | __le32 Timeout; | 698 | __le32 Timeout; |
699 | __le32 Reserved; | 699 | __le32 Reserved; |
700 | __u16 ByteCount; /* file name follows */ | 700 | __le16 ByteCount; /* file name follows */ |
701 | char fileName[1]; | 701 | char fileName[1]; |
702 | } OPENX_REQ; | 702 | } OPENX_REQ; |
703 | 703 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0bace385e97a..dc5a6a6ff2f9 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -56,6 +56,7 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); | |||
56 | extern int is_valid_oplock_break(struct smb_hdr *smb); | 56 | extern int is_valid_oplock_break(struct smb_hdr *smb); |
57 | extern int is_size_safe_to_change(struct cifsInodeInfo *); | 57 | extern int is_size_safe_to_change(struct cifsInodeInfo *); |
58 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 58 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
59 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | ||
59 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 60 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
60 | enum securityEnum *secType); | 61 | enum securityEnum *secType); |
61 | extern int cifs_inet_pton(int, char * source, void *dst); | 62 | extern int cifs_inet_pton(int, char * source, void *dst); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index daf717e6b6eb..52caac063a77 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -779,7 +779,7 @@ OldOpenRetry: | |||
779 | /* BB FIXME END BB */ | 779 | /* BB FIXME END BB */ |
780 | 780 | ||
781 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | 781 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); |
782 | pSMB->OpenFunction = convert_disposition(openDisposition); | 782 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); |
783 | count += name_len; | 783 | count += name_len; |
784 | pSMB->hdr.smb_buf_length += count; | 784 | pSMB->hdr.smb_buf_length += count; |
785 | 785 | ||
@@ -808,10 +808,12 @@ OldOpenRetry: | |||
808 | pfile_info->LastAccessTime = 0; /* BB fixme */ | 808 | pfile_info->LastAccessTime = 0; /* BB fixme */ |
809 | pfile_info->LastWriteTime = 0; /* BB fixme */ | 809 | pfile_info->LastWriteTime = 0; /* BB fixme */ |
810 | pfile_info->ChangeTime = 0; /* BB fixme */ | 810 | pfile_info->ChangeTime = 0; /* BB fixme */ |
811 | pfile_info->Attributes = pSMBr->FileAttributes; | 811 | pfile_info->Attributes = |
812 | cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes)); | ||
812 | /* the file_info buf is endian converted by caller */ | 813 | /* the file_info buf is endian converted by caller */ |
813 | pfile_info->AllocationSize = pSMBr->EndOfFile; | 814 | pfile_info->AllocationSize = |
814 | pfile_info->EndOfFile = pSMBr->EndOfFile; | 815 | cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile)); |
816 | pfile_info->EndOfFile = pfile_info->AllocationSize; | ||
815 | pfile_info->NumberOfLinks = cpu_to_le32(1); | 817 | pfile_info->NumberOfLinks = cpu_to_le32(1); |
816 | } | 818 | } |
817 | } | 819 | } |
@@ -2390,9 +2392,11 @@ QInfRetry: | |||
2390 | cFYI(1, ("Send error in QueryInfo = %d", rc)); | 2392 | cFYI(1, ("Send error in QueryInfo = %d", rc)); |
2391 | } else if (pFinfo) { /* decode response */ | 2393 | } else if (pFinfo) { /* decode response */ |
2392 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); | 2394 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); |
2393 | pFinfo->AllocationSize = (__le64) pSMBr->size; | 2395 | pFinfo->AllocationSize = |
2394 | pFinfo->EndOfFile = (__le64) pSMBr->size; | 2396 | cpu_to_le64(le32_to_cpu(pSMBr->size)); |
2395 | pFinfo->Attributes = (__le32) pSMBr->attr; | 2397 | pFinfo->EndOfFile = pFinfo->AllocationSize; |
2398 | pFinfo->Attributes = | ||
2399 | cpu_to_le32(le16_to_cpu(pSMBr->attr)); | ||
2396 | } else | 2400 | } else |
2397 | rc = -EIO; /* bad buffer passed in */ | 2401 | rc = -EIO; /* bad buffer passed in */ |
2398 | 2402 | ||
@@ -3722,16 +3726,16 @@ QFSPosixRetry: | |||
3722 | le64_to_cpu(response_data->TotalBlocks); | 3726 | le64_to_cpu(response_data->TotalBlocks); |
3723 | FSData->f_bfree = | 3727 | FSData->f_bfree = |
3724 | le64_to_cpu(response_data->BlocksAvail); | 3728 | le64_to_cpu(response_data->BlocksAvail); |
3725 | if(response_data->UserBlocksAvail == -1) { | 3729 | if(response_data->UserBlocksAvail == cpu_to_le64(-1)) { |
3726 | FSData->f_bavail = FSData->f_bfree; | 3730 | FSData->f_bavail = FSData->f_bfree; |
3727 | } else { | 3731 | } else { |
3728 | FSData->f_bavail = | 3732 | FSData->f_bavail = |
3729 | le64_to_cpu(response_data->UserBlocksAvail); | 3733 | le64_to_cpu(response_data->UserBlocksAvail); |
3730 | } | 3734 | } |
3731 | if(response_data->TotalFileNodes != -1) | 3735 | if(response_data->TotalFileNodes != cpu_to_le64(-1)) |
3732 | FSData->f_files = | 3736 | FSData->f_files = |
3733 | le64_to_cpu(response_data->TotalFileNodes); | 3737 | le64_to_cpu(response_data->TotalFileNodes); |
3734 | if(response_data->FreeFileNodes != -1) | 3738 | if(response_data->FreeFileNodes != cpu_to_le64(-1)) |
3735 | FSData->f_ffree = | 3739 | FSData->f_ffree = |
3736 | le64_to_cpu(response_data->FreeFileNodes); | 3740 | le64_to_cpu(response_data->FreeFileNodes); |
3737 | } | 3741 | } |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 196976049c00..e27e5ad8b591 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -303,12 +303,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) | |||
303 | byte_count += total_in_buf2; | 303 | byte_count += total_in_buf2; |
304 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 304 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); |
305 | 305 | ||
306 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 306 | byte_count = pTargetSMB->smb_buf_length; |
307 | byte_count += total_in_buf2; | 307 | byte_count += total_in_buf2; |
308 | 308 | ||
309 | /* BB also add check that we are not beyond maximum buffer size */ | 309 | /* BB also add check that we are not beyond maximum buffer size */ |
310 | 310 | ||
311 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 311 | pTargetSMB->smb_buf_length = byte_count; |
312 | 312 | ||
313 | if(remaining == total_in_buf2) { | 313 | if(remaining == total_in_buf2) { |
314 | cFYI(1,("found the last secondary response")); | 314 | cFYI(1,("found the last secondary response")); |
@@ -333,7 +333,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
333 | struct cifsSesInfo *ses; | 333 | struct cifsSesInfo *ses; |
334 | struct task_struct *task_to_wake = NULL; | 334 | struct task_struct *task_to_wake = NULL; |
335 | struct mid_q_entry *mid_entry; | 335 | struct mid_q_entry *mid_entry; |
336 | char *temp; | 336 | char temp; |
337 | int isLargeBuf = FALSE; | 337 | int isLargeBuf = FALSE; |
338 | int isMultiRsp; | 338 | int isMultiRsp; |
339 | int reconnect; | 339 | int reconnect; |
@@ -435,22 +435,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
435 | continue; | 435 | continue; |
436 | } | 436 | } |
437 | 437 | ||
438 | /* the right amount was read from socket - 4 bytes */ | 438 | /* The right amount was read from socket - 4 bytes */ |
439 | /* so we can now interpret the length field */ | ||
439 | 440 | ||
441 | /* the first byte big endian of the length field, | ||
442 | is actually not part of the length but the type | ||
443 | with the most common, zero, as regular data */ | ||
444 | temp = *((char *) smb_buffer); | ||
445 | |||
446 | /* Note that FC 1001 length is big endian on the wire, | ||
447 | but we convert it here so it is always manipulated | ||
448 | as host byte order */ | ||
440 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 449 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
441 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); | 450 | smb_buffer->smb_buf_length = pdu_length; |
451 | |||
452 | cFYI(1,("rfc1002 length 0x%x)", pdu_length+4)); | ||
442 | 453 | ||
443 | temp = (char *) smb_buffer; | 454 | if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { |
444 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | ||
445 | continue; | 455 | continue; |
446 | } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { | 456 | } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { |
447 | cFYI(1,("Good RFC 1002 session rsp")); | 457 | cFYI(1,("Good RFC 1002 session rsp")); |
448 | continue; | 458 | continue; |
449 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | 459 | } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
450 | /* we get this from Windows 98 instead of | 460 | /* we get this from Windows 98 instead of |
451 | an error on SMB negprot response */ | 461 | an error on SMB negprot response */ |
452 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", | 462 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", |
453 | temp[4])); | 463 | pdu_length)); |
454 | if(server->tcpStatus == CifsNew) { | 464 | if(server->tcpStatus == CifsNew) { |
455 | /* if nack on negprot (rather than | 465 | /* if nack on negprot (rather than |
456 | ret of smb negprot error) reconnecting | 466 | ret of smb negprot error) reconnecting |
@@ -472,9 +482,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
472 | wake_up(&server->response_q); | 482 | wake_up(&server->response_q); |
473 | continue; | 483 | continue; |
474 | } | 484 | } |
475 | } else if (temp[0] != (char) 0) { | 485 | } else if (temp != (char) 0) { |
476 | cERROR(1,("Unknown RFC 1002 frame")); | 486 | cERROR(1,("Unknown RFC 1002 frame")); |
477 | cifs_dump_mem(" Received Data: ", temp, length); | 487 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |
488 | length); | ||
478 | cifs_reconnect(server); | 489 | cifs_reconnect(server); |
479 | csocket = server->ssocket; | 490 | csocket = server->ssocket; |
480 | continue; | 491 | continue; |
@@ -609,7 +620,8 @@ multi_t2_fnd: | |||
609 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) | 620 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) |
610 | && (isMultiRsp == FALSE)) { | 621 | && (isMultiRsp == FALSE)) { |
611 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 622 | cERROR(1, ("No task to wake, unknown frame rcvd!")); |
612 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | 623 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, |
624 | sizeof(struct smb_hdr)); | ||
613 | } | 625 | } |
614 | } /* end while !EXITING */ | 626 | } /* end while !EXITING */ |
615 | 627 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 26b35b55f31b..8a0edd695f84 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -419,7 +419,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) | |||
419 | int | 419 | int |
420 | checkSMB(struct smb_hdr *smb, __u16 mid, int length) | 420 | checkSMB(struct smb_hdr *smb, __u16 mid, int length) |
421 | { | 421 | { |
422 | __u32 len = be32_to_cpu(smb->smb_buf_length); | 422 | __u32 len = smb->smb_buf_length; |
423 | cFYI(0, | 423 | cFYI(0, |
424 | ("Entering checkSMB with Length: %x, smb_buf_length: %x ", | 424 | ("Entering checkSMB with Length: %x, smb_buf_length: %x ", |
425 | length, len)); | 425 | length, len)); |
@@ -448,9 +448,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
448 | if (checkSMBhdr(smb, mid)) | 448 | if (checkSMBhdr(smb, mid)) |
449 | return 1; | 449 | return 1; |
450 | 450 | ||
451 | if ((4 + len != smbCalcSize(smb)) | 451 | if ((4 + len != smbCalcSize_LE(smb)) |
452 | || (4 + len != (unsigned int)length)) { | 452 | || (4 + len != (unsigned int)length)) { |
453 | cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); | 453 | cERROR(1, ("smbCalcSize %x ", smbCalcSize_LE(smb))); |
454 | cERROR(1, | 454 | cERROR(1, |
455 | ("bad smb size detected. The Mid=%d", smb->Mid)); | 455 | ("bad smb size detected. The Mid=%d", smb->Mid)); |
456 | return 1; | 456 | return 1; |
@@ -672,6 +672,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | |||
672 | int i,j,charlen; | 672 | int i,j,charlen; |
673 | int len_remaining = maxlen; | 673 | int len_remaining = maxlen; |
674 | char src_char; | 674 | char src_char; |
675 | __u16 temp; | ||
675 | 676 | ||
676 | if(!mapChars) | 677 | if(!mapChars) |
677 | return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); | 678 | return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); |
@@ -708,13 +709,14 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | |||
708 | break;*/ | 709 | break;*/ |
709 | default: | 710 | default: |
710 | charlen = cp->char2uni(source+i, | 711 | charlen = cp->char2uni(source+i, |
711 | len_remaining, target+j); | 712 | len_remaining, &temp); |
712 | /* if no match, use question mark, which | 713 | /* if no match, use question mark, which |
713 | at least in some cases servers as wild card */ | 714 | at least in some cases servers as wild card */ |
714 | if(charlen < 1) { | 715 | if(charlen < 1) { |
715 | target[j] = cpu_to_le16(0x003f); | 716 | target[j] = cpu_to_le16(0x003f); |
716 | charlen = 1; | 717 | charlen = 1; |
717 | } | 718 | } else |
719 | target[j] = cpu_to_le16(temp); | ||
718 | len_remaining -= charlen; | 720 | len_remaining -= charlen; |
719 | /* character may take more than one byte in the | 721 | /* character may take more than one byte in the |
720 | the source string, but will take exactly two | 722 | the source string, but will take exactly two |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 32efa32774d2..29e6efc5597c 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -868,7 +868,14 @@ unsigned int | |||
868 | smbCalcSize(struct smb_hdr *ptr) | 868 | smbCalcSize(struct smb_hdr *ptr) |
869 | { | 869 | { |
870 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + | 870 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + |
871 | 2 /* size of the bcc field itself */ + BCC(ptr)); | 871 | 2 /* size of the bcc field */ + BCC(ptr)); |
872 | } | ||
873 | |||
874 | unsigned int | ||
875 | smbCalcSize_LE(struct smb_hdr *ptr) | ||
876 | { | ||
877 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + | ||
878 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); | ||
872 | } | 879 | } |
873 | 880 | ||
874 | /* The following are taken from fs/ntfs/util.c */ | 881 | /* The following are taken from fs/ntfs/util.c */ |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index d5e0c4018f92..9e8e85a8d186 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -414,7 +414,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
414 | spin_lock(&GlobalMid_Lock); | 414 | spin_lock(&GlobalMid_Lock); |
415 | if (midQ->resp_buf) { | 415 | if (midQ->resp_buf) { |
416 | spin_unlock(&GlobalMid_Lock); | 416 | spin_unlock(&GlobalMid_Lock); |
417 | receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf); | 417 | receive_len = midQ->resp_buf->smb_buf_length; |
418 | } else { | 418 | } else { |
419 | cERROR(1,("No response buffer")); | 419 | cERROR(1,("No response buffer")); |
420 | if(midQ->midState == MID_REQUEST_SUBMITTED) { | 420 | if(midQ->midState == MID_REQUEST_SUBMITTED) { |
@@ -665,7 +665,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
665 | spin_lock(&GlobalMid_Lock); | 665 | spin_lock(&GlobalMid_Lock); |
666 | if (midQ->resp_buf) { | 666 | if (midQ->resp_buf) { |
667 | spin_unlock(&GlobalMid_Lock); | 667 | spin_unlock(&GlobalMid_Lock); |
668 | receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf); | 668 | receive_len = midQ->resp_buf->smb_buf_length; |
669 | } else { | 669 | } else { |
670 | cERROR(1,("No response buffer")); | 670 | cERROR(1,("No response buffer")); |
671 | if(midQ->midState == MID_REQUEST_SUBMITTED) { | 671 | if(midQ->midState == MID_REQUEST_SUBMITTED) { |