diff options
-rw-r--r-- | fs/cifs/sess.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 5c68b4282be9..70d04d08293b 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -285,27 +285,26 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
285 | int words_left, len; | 285 | int words_left, len; |
286 | char *data = *pbcc_area; | 286 | char *data = *pbcc_area; |
287 | 287 | ||
288 | |||
289 | |||
290 | cFYI(1, ("bleft %d", bleft)); | 288 | cFYI(1, ("bleft %d", bleft)); |
291 | 289 | ||
292 | 290 | /* | |
293 | /* SMB header is unaligned, so cifs servers word align start of | 291 | * Windows servers do not always double null terminate their final |
294 | Unicode strings */ | 292 | * Unicode string. Check to see if there are an uneven number of bytes |
295 | data++; | 293 | * left. If so, then add an extra NULL pad byte to the end of the |
296 | bleft--; /* Windows servers do not always double null terminate | 294 | * response. |
297 | their final Unicode string - in which case we | 295 | * |
298 | now will not attempt to decode the byte of junk | 296 | * See section 2.7.2 in "Implementing CIFS" for details |
299 | which follows it */ | 297 | */ |
298 | if (bleft % 2) { | ||
299 | data[bleft] = 0; | ||
300 | ++bleft; | ||
301 | } | ||
300 | 302 | ||
301 | words_left = bleft / 2; | 303 | words_left = bleft / 2; |
302 | 304 | ||
303 | /* save off server operating system */ | 305 | /* save off server operating system */ |
304 | len = UniStrnlen((wchar_t *) data, words_left); | 306 | len = UniStrnlen((wchar_t *) data, words_left); |
305 | 307 | ||
306 | /* We look for obvious messed up bcc or strings in response so we do not go off | ||
307 | the end since (at least) WIN2K and Windows XP have a major bug in not null | ||
308 | terminating last Unicode string in response */ | ||
309 | if (len >= words_left) | 308 | if (len >= words_left) |
310 | return rc; | 309 | return rc; |
311 | 310 | ||
@@ -343,13 +342,10 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
343 | return rc; | 342 | return rc; |
344 | 343 | ||
345 | kfree(ses->serverDomain); | 344 | kfree(ses->serverDomain); |
346 | ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ | 345 | ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL); |
347 | if (ses->serverDomain != NULL) { | 346 | if (ses->serverDomain != NULL) |
348 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, | 347 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, |
349 | nls_cp); | 348 | nls_cp); |
350 | ses->serverDomain[2*len] = 0; | ||
351 | ses->serverDomain[(2*len) + 1] = 0; | ||
352 | } | ||
353 | data += 2 * (len + 1); | 349 | data += 2 * (len + 1); |
354 | words_left -= len + 1; | 350 | words_left -= len + 1; |
355 | 351 | ||
@@ -702,12 +698,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
702 | } | 698 | } |
703 | 699 | ||
704 | /* BB check if Unicode and decode strings */ | 700 | /* BB check if Unicode and decode strings */ |
705 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) | 701 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) { |
702 | /* unicode string area must be word-aligned */ | ||
703 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { | ||
704 | ++bcc_ptr; | ||
705 | --bytes_remaining; | ||
706 | } | ||
706 | rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, | 707 | rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, |
707 | ses, nls_cp); | 708 | ses, nls_cp); |
708 | else | 709 | } else { |
709 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, | 710 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, |
710 | ses, nls_cp); | 711 | ses, nls_cp); |
712 | } | ||
711 | 713 | ||
712 | ssetup_exit: | 714 | ssetup_exit: |
713 | if (spnego_key) { | 715 | if (spnego_key) { |