Commit 47fc7731 authored by Pavel Shilovsky's avatar Pavel Shilovsky

Update 2.6.38 sources from stable (v2.6.38.7)

parent c298cd36
...@@ -90,7 +90,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, ...@@ -90,7 +90,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
case UNI_COLON: case UNI_COLON:
*target = ':'; *target = ':';
break; break;
case UNI_ASTERIK: case UNI_ASTERISK:
*target = '*'; *target = '*';
break; break;
case UNI_QUESTION: case UNI_QUESTION:
...@@ -264,40 +264,41 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, ...@@ -264,40 +264,41 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
* names are little endian 16 bit Unicode on the wire * names are little endian 16 bit Unicode on the wire
*/ */
int int
cifsConvertToUCS(__le16 *target, const char *source, int maxlen, cifsConvertToUCS(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapChars) const struct nls_table *cp, int mapChars)
{ {
int i, j, charlen; int i, j, charlen;
int len_remaining = maxlen;
char src_char; char src_char;
__u16 temp; __le16 dst_char;
wchar_t tmp;
if (!mapChars) if (!mapChars)
return cifs_strtoUCS(target, source, PATH_MAX, cp); return cifs_strtoUCS(target, source, PATH_MAX, cp);
for (i = 0, j = 0; i < maxlen; j++) { for (i = 0, j = 0; i < srclen; j++) {
src_char = source[i]; src_char = source[i];
charlen = 1;
switch (src_char) { switch (src_char) {
case 0: case 0:
put_unaligned_le16(0, &target[j]); put_unaligned(0, &target[j]);
goto ctoUCS_out; goto ctoUCS_out;
case ':': case ':':
temp = UNI_COLON; dst_char = cpu_to_le16(UNI_COLON);
break; break;
case '*': case '*':
temp = UNI_ASTERIK; dst_char = cpu_to_le16(UNI_ASTERISK);
break; break;
case '?': case '?':
temp = UNI_QUESTION; dst_char = cpu_to_le16(UNI_QUESTION);
break; break;
case '<': case '<':
temp = UNI_LESSTHAN; dst_char = cpu_to_le16(UNI_LESSTHAN);
break; break;
case '>': case '>':
temp = UNI_GRTRTHAN; dst_char = cpu_to_le16(UNI_GRTRTHAN);
break; break;
case '|': case '|':
temp = UNI_PIPE; dst_char = cpu_to_le16(UNI_PIPE);
break; break;
/* /*
* FIXME: We can not handle remapping backslash (UNI_SLASH) * FIXME: We can not handle remapping backslash (UNI_SLASH)
...@@ -305,28 +306,24 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen, ...@@ -305,28 +306,24 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
* as they use backslash as separator. * as they use backslash as separator.
*/ */
default: default:
charlen = cp->char2uni(source+i, len_remaining, charlen = cp->char2uni(source + i, srclen - i, &tmp);
&temp); dst_char = cpu_to_le16(tmp);
/* /*
* if no match, use question mark, which at least in * if no match, use question mark, which at least in
* some cases serves as wild card * some cases serves as wild card
*/ */
if (charlen < 1) { if (charlen < 1) {
temp = 0x003f; dst_char = cpu_to_le16(0x003f);
charlen = 1; charlen = 1;
} }
len_remaining -= charlen; }
/* /*
* character may take more than one byte in the source * character may take more than one byte in the source string,
* string, but will take exactly two bytes in the * but will take exactly two bytes in the target string
* target string
*/ */
i += charlen; i += charlen;
continue; put_unaligned(dst_char, &target[j]);
}
put_unaligned_le16(temp, &target[j]);
i++; /* move to next char in source string */
len_remaining--;
} }
ctoUCS_out: ctoUCS_out:
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
* reserved symbols (along with \ and /), otherwise illegal to store * reserved symbols (along with \ and /), otherwise illegal to store
* in filenames in NTFS * in filenames in NTFS
*/ */
#define UNI_ASTERIK (__u16) ('*' + 0xF000) #define UNI_ASTERISK (__u16) ('*' + 0xF000)
#define UNI_QUESTION (__u16) ('?' + 0xF000) #define UNI_QUESTION (__u16) ('?' + 0xF000)
#define UNI_COLON (__u16) (':' + 0xF000) #define UNI_COLON (__u16) (':' + 0xF000)
#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) #define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
......
...@@ -276,7 +276,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) ...@@ -276,7 +276,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
char *data_area_of_target; char *data_area_of_target;
char *data_area_of_buf2; char *data_area_of_buf2;
int remaining; int remaining;
__u16 byte_count, total_data_size, total_in_buf, total_in_buf2; unsigned int byte_count, total_in_buf;
__u16 total_data_size, total_in_buf2;
total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
...@@ -289,7 +290,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) ...@@ -289,7 +290,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
remaining = total_data_size - total_in_buf; remaining = total_data_size - total_in_buf;
if (remaining < 0) if (remaining < 0)
return -EINVAL; return -EPROTO;
if (remaining == 0) /* nothing to do, ignore */ if (remaining == 0) /* nothing to do, ignore */
return 0; return 0;
...@@ -310,20 +311,29 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) ...@@ -310,20 +311,29 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
data_area_of_target += total_in_buf; data_area_of_target += total_in_buf;
/* copy second buffer into end of first buffer */ /* copy second buffer into end of first buffer */
memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
total_in_buf += total_in_buf2; total_in_buf += total_in_buf2;
/* is the result too big for the field? */
if (total_in_buf > USHRT_MAX)
return -EPROTO;
put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
/* fix up the BCC */
byte_count = get_bcc_le(pTargetSMB); byte_count = get_bcc_le(pTargetSMB);
byte_count += total_in_buf2; byte_count += total_in_buf2;
/* is the result too big for the field? */
if (byte_count > USHRT_MAX)
return -EPROTO;
put_bcc_le(byte_count, pTargetSMB); put_bcc_le(byte_count, pTargetSMB);
byte_count = pTargetSMB->smb_buf_length; byte_count = pTargetSMB->smb_buf_length;
byte_count += total_in_buf2; byte_count += total_in_buf2;
/* don't allow buffer to overflow */
/* BB also add check that we are not beyond maximum buffer size */ if (byte_count > CIFSMaxBufSize)
return -ENOBUFS;
pTargetSMB->smb_buf_length = byte_count; pTargetSMB->smb_buf_length = byte_count;
memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
if (remaining == total_in_buf2) { if (remaining == total_in_buf2) {
cFYI(1, "found the last secondary response"); cFYI(1, "found the last secondary response");
return 0; /* we are done */ return 0; /* we are done */
...@@ -609,37 +619,45 @@ incomplete_rcv: ...@@ -609,37 +619,45 @@ incomplete_rcv:
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead); mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if ((mid_entry->mid == smb_buffer->Mid) && if (mid_entry->mid != smb_buffer->Mid ||
(mid_entry->midState == MID_REQUEST_SUBMITTED) && mid_entry->midState != MID_REQUEST_SUBMITTED ||
(mid_entry->command == smb_buffer->Command)) { mid_entry->command != smb_buffer->Command) {
mid_entry = NULL;
continue;
}
if (length == 0 && if (length == 0 &&
check2ndT2(smb_buffer, server->maxBuf) > 0) { check2ndT2(smb_buffer, server->maxBuf) > 0) {
/* We have a multipart transact2 resp */ /* We have a multipart transact2 resp */
isMultiRsp = true; isMultiRsp = true;
if (mid_entry->resp_buf) { if (mid_entry->resp_buf) {
/* merge response - fix up 1st*/ /* merge response - fix up 1st*/
if (coalesce_t2(smb_buffer, length = coalesce_t2(smb_buffer,
mid_entry->resp_buf)) { mid_entry->resp_buf);
mid_entry->multiRsp = if (length > 0) {
true; length = 0;
mid_entry->multiRsp = true;
break; break;
} else { } else {
/* all parts received */ /* all parts received or
mid_entry->multiEnd = * packet is malformed
true; */
mid_entry->multiEnd = true;
goto multi_t2_fnd; goto multi_t2_fnd;
} }
} else { } else {
if (!isLargeBuf) { if (!isLargeBuf) {
cERROR(1, "1st trans2 resp needs bigbuf"); /*
/* BB maybe we can fix this up, switch * FIXME: switch to already
to already allocated large buffer? */ * allocated largebuf?
*/
cERROR(1, "1st trans2 resp "
"needs bigbuf");
} else { } else {
/* Have first buffer */ /* Have first buffer */
mid_entry->resp_buf = mid_entry->resp_buf =
smb_buffer; smb_buffer;
mid_entry->largeBuf = mid_entry->largeBuf = true;
true;
bigbuf = NULL; bigbuf = NULL;
} }
} }
...@@ -649,11 +667,9 @@ incomplete_rcv: ...@@ -649,11 +667,9 @@ incomplete_rcv:
mid_entry->largeBuf = isLargeBuf; mid_entry->largeBuf = isLargeBuf;
multi_t2_fnd: multi_t2_fnd:
if (length == 0) if (length == 0)
mid_entry->midState = mid_entry->midState = MID_RESPONSE_RECEIVED;
MID_RESPONSE_RECEIVED;
else else
mid_entry->midState = mid_entry->midState = MID_RESPONSE_MALFORMED;
MID_RESPONSE_MALFORMED;
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
mid_entry->when_received = jiffies; mid_entry->when_received = jiffies;
#endif #endif
...@@ -661,8 +677,6 @@ multi_t2_fnd: ...@@ -661,8 +677,6 @@ multi_t2_fnd:
mid_entry->callback(mid_entry); mid_entry->callback(mid_entry);
break; break;
} }
mid_entry = NULL;
}
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if (mid_entry != NULL) { if (mid_entry != NULL) {
...@@ -2650,6 +2664,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, ...@@ -2650,6 +2664,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon,
0 /* not legacy */, cifs_sb->local_nls, 0 /* not legacy */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == -EOPNOTSUPP || rc == -EINVAL)
rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(pfile_info); kfree(pfile_info);
return rc; return rc;
} }
......
...@@ -277,7 +277,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, ...@@ -277,7 +277,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
} }
static void static void
decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
const struct nls_table *nls_cp) const struct nls_table *nls_cp)
{ {
int len; int len;
...@@ -285,19 +285,6 @@ decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, ...@@ -285,19 +285,6 @@ decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses,
cFYI(1, "bleft %d", bleft); cFYI(1, "bleft %d", bleft);
/*
* Windows servers do not always double null terminate their final
* Unicode string. Check to see if there are an uneven number of bytes
* left. If so, then add an extra NULL pad byte to the end of the
* response.
*
* See section 2.7.2 in "Implementing CIFS" for details
*/
if (bleft % 2) {
data[bleft] = 0;
++bleft;
}
kfree(ses->serverOS); kfree(ses->serverOS);
ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
cFYI(1, "serverOS=%s", ses->serverOS); cFYI(1, "serverOS=%s", ses->serverOS);
...@@ -930,7 +917,9 @@ ssetup_ntlmssp_authenticate: ...@@ -930,7 +917,9 @@ ssetup_ntlmssp_authenticate:
} }
/* BB check if Unicode and decode strings */ /* BB check if Unicode and decode strings */
if (smb_buf->Flags2 & SMBFLG2_UNICODE) { if (bytes_remaining == 0) {
/* no string area to decode, do nothing */
} else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
/* unicode string area must be word-aligned */ /* unicode string area must be word-aligned */
if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
++bcc_ptr; ++bcc_ptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment