aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-06 18:32:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-06 18:32:41 -0400
commitc2bf807eb347325988b1c7f9139e934ed9b1d795 (patch)
tree3b35c66365a3a5e2d10183d05a014d8e26196e6c /fs
parenta3a4a5acd3bd2f6f1e102e1f1b9d2e2bb320a7fd (diff)
parent16541ba11c4f04ffe94b073e301f00b749fb84a1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: handle errors from coalesce_t2 cifs: refactor mid finding loop in cifs_demultiplex_thread cifs: sanitize length checking in coalesce_t2 (try #3) cifs: check for bytes_remaining going to zero in CIFS_SessSetup cifs: change bleft in decode_unicode_ssetup back to signed type
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/connect.c120
-rw-r--r--fs/cifs/sess.c19
2 files changed, 71 insertions, 68 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4bc862a80efa..05f1dcf7d79a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -274,7 +274,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
274 char *data_area_of_target; 274 char *data_area_of_target;
275 char *data_area_of_buf2; 275 char *data_area_of_buf2;
276 int remaining; 276 int remaining;
277 __u16 byte_count, total_data_size, total_in_buf, total_in_buf2; 277 unsigned int byte_count, total_in_buf;
278 __u16 total_data_size, total_in_buf2;
278 279
279 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); 280 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
280 281
@@ -287,7 +288,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
287 remaining = total_data_size - total_in_buf; 288 remaining = total_data_size - total_in_buf;
288 289
289 if (remaining < 0) 290 if (remaining < 0)
290 return -EINVAL; 291 return -EPROTO;
291 292
292 if (remaining == 0) /* nothing to do, ignore */ 293 if (remaining == 0) /* nothing to do, ignore */
293 return 0; 294 return 0;
@@ -308,20 +309,29 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
308 data_area_of_target += total_in_buf; 309 data_area_of_target += total_in_buf;
309 310
310 /* copy second buffer into end of first buffer */ 311 /* copy second buffer into end of first buffer */
311 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
312 total_in_buf += total_in_buf2; 312 total_in_buf += total_in_buf2;
313 /* is the result too big for the field? */
314 if (total_in_buf > USHRT_MAX)
315 return -EPROTO;
313 put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); 316 put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
317
318 /* fix up the BCC */
314 byte_count = get_bcc_le(pTargetSMB); 319 byte_count = get_bcc_le(pTargetSMB);
315 byte_count += total_in_buf2; 320 byte_count += total_in_buf2;
321 /* is the result too big for the field? */
322 if (byte_count > USHRT_MAX)
323 return -EPROTO;
316 put_bcc_le(byte_count, pTargetSMB); 324 put_bcc_le(byte_count, pTargetSMB);
317 325
318 byte_count = pTargetSMB->smb_buf_length; 326 byte_count = pTargetSMB->smb_buf_length;
319 byte_count += total_in_buf2; 327 byte_count += total_in_buf2;
320 328 /* don't allow buffer to overflow */
321 /* BB also add check that we are not beyond maximum buffer size */ 329 if (byte_count > CIFSMaxBufSize)
322 330 return -ENOBUFS;
323 pTargetSMB->smb_buf_length = byte_count; 331 pTargetSMB->smb_buf_length = byte_count;
324 332
333 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
334
325 if (remaining == total_in_buf2) { 335 if (remaining == total_in_buf2) {
326 cFYI(1, "found the last secondary response"); 336 cFYI(1, "found the last secondary response");
327 return 0; /* we are done */ 337 return 0; /* we are done */
@@ -607,59 +617,63 @@ incomplete_rcv:
607 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 617 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
608 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 618 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
609 619
610 if ((mid_entry->mid == smb_buffer->Mid) && 620 if (mid_entry->mid != smb_buffer->Mid ||
611 (mid_entry->midState == MID_REQUEST_SUBMITTED) && 621 mid_entry->midState != MID_REQUEST_SUBMITTED ||
612 (mid_entry->command == smb_buffer->Command)) { 622 mid_entry->command != smb_buffer->Command) {
613 if (length == 0 && 623 mid_entry = NULL;
614 check2ndT2(smb_buffer, server->maxBuf) > 0) { 624 continue;
615 /* We have a multipart transact2 resp */ 625 }
616 isMultiRsp = true; 626
617 if (mid_entry->resp_buf) { 627 if (length == 0 &&
618 /* merge response - fix up 1st*/ 628 check2ndT2(smb_buffer, server->maxBuf) > 0) {
619 if (coalesce_t2(smb_buffer, 629 /* We have a multipart transact2 resp */
620 mid_entry->resp_buf)) { 630 isMultiRsp = true;
621 mid_entry->multiRsp = 631 if (mid_entry->resp_buf) {
622 true; 632 /* merge response - fix up 1st*/
623 break; 633 length = coalesce_t2(smb_buffer,
624 } else { 634 mid_entry->resp_buf);
625 /* all parts received */ 635 if (length > 0) {
626 mid_entry->multiEnd = 636 length = 0;
627 true; 637 mid_entry->multiRsp = true;
628 goto multi_t2_fnd; 638 break;
629 }
630 } else { 639 } else {
631 if (!isLargeBuf) { 640 /* all parts received or
632 cERROR(1, "1st trans2 resp needs bigbuf"); 641 * packet is malformed
633 /* BB maybe we can fix this up, switch 642 */
634 to already allocated large buffer? */ 643 mid_entry->multiEnd = true;
635 } else { 644 goto multi_t2_fnd;
636 /* Have first buffer */ 645 }
637 mid_entry->resp_buf = 646 } else {
638 smb_buffer; 647 if (!isLargeBuf) {
639 mid_entry->largeBuf = 648 /*
640 true; 649 * FIXME: switch to already
641 bigbuf = NULL; 650 * allocated largebuf?
642 } 651 */
652 cERROR(1, "1st trans2 resp "
653 "needs bigbuf");
654 } else {
655 /* Have first buffer */
656 mid_entry->resp_buf =
657 smb_buffer;
658 mid_entry->largeBuf = true;
659 bigbuf = NULL;
643 } 660 }
644 break;
645 } 661 }
646 mid_entry->resp_buf = smb_buffer; 662 break;
647 mid_entry->largeBuf = isLargeBuf; 663 }
664 mid_entry->resp_buf = smb_buffer;
665 mid_entry->largeBuf = isLargeBuf;
648multi_t2_fnd: 666multi_t2_fnd:
649 if (length == 0) 667 if (length == 0)
650 mid_entry->midState = 668 mid_entry->midState = MID_RESPONSE_RECEIVED;
651 MID_RESPONSE_RECEIVED; 669 else
652 else 670 mid_entry->midState = MID_RESPONSE_MALFORMED;
653 mid_entry->midState =
654 MID_RESPONSE_MALFORMED;
655#ifdef CONFIG_CIFS_STATS2 671#ifdef CONFIG_CIFS_STATS2
656 mid_entry->when_received = jiffies; 672 mid_entry->when_received = jiffies;
657#endif 673#endif
658 list_del_init(&mid_entry->qhead); 674 list_del_init(&mid_entry->qhead);
659 mid_entry->callback(mid_entry); 675 mid_entry->callback(mid_entry);
660 break; 676 break;
661 }
662 mid_entry = NULL;
663 } 677 }
664 spin_unlock(&GlobalMid_Lock); 678 spin_unlock(&GlobalMid_Lock);
665 679
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index f6728eb6f4b9..645114ad0a10 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -276,7 +276,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
276} 276}
277 277
278static void 278static void
279decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, 279decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
280 const struct nls_table *nls_cp) 280 const struct nls_table *nls_cp)
281{ 281{
282 int len; 282 int len;
@@ -284,19 +284,6 @@ decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses,
284 284
285 cFYI(1, "bleft %d", bleft); 285 cFYI(1, "bleft %d", bleft);
286 286
287 /*
288 * Windows servers do not always double null terminate their final
289 * Unicode string. Check to see if there are an uneven number of bytes
290 * left. If so, then add an extra NULL pad byte to the end of the
291 * response.
292 *
293 * See section 2.7.2 in "Implementing CIFS" for details
294 */
295 if (bleft % 2) {
296 data[bleft] = 0;
297 ++bleft;
298 }
299
300 kfree(ses->serverOS); 287 kfree(ses->serverOS);
301 ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); 288 ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
302 cFYI(1, "serverOS=%s", ses->serverOS); 289 cFYI(1, "serverOS=%s", ses->serverOS);
@@ -929,7 +916,9 @@ ssetup_ntlmssp_authenticate:
929 } 916 }
930 917
931 /* BB check if Unicode and decode strings */ 918 /* BB check if Unicode and decode strings */
932 if (smb_buf->Flags2 & SMBFLG2_UNICODE) { 919 if (bytes_remaining == 0) {
920 /* no string area to decode, do nothing */
921 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
933 /* unicode string area must be word-aligned */ 922 /* unicode string area must be word-aligned */
934 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { 923 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
935 ++bcc_ptr; 924 ++bcc_ptr;