aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c378
1 files changed, 196 insertions, 182 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index ff8243a8fe3e..7ebe6599ed3a 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -37,15 +37,11 @@ extern mempool_t *cifs_mid_poolp;
37extern struct kmem_cache *cifs_oplock_cachep; 37extern struct kmem_cache *cifs_oplock_cachep;
38 38
39static struct mid_q_entry * 39static struct mid_q_entry *
40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41{ 41{
42 struct mid_q_entry *temp; 42 struct mid_q_entry *temp;
43 43
44 if (ses == NULL) { 44 if (server == NULL) {
45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
46 return NULL;
47 }
48 if (ses->server == NULL) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry")); 45 cERROR(1, ("Null TCP session in AllocMidQEntry"));
50 return NULL; 46 return NULL;
51 } 47 }
@@ -62,12 +58,11 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ 58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */ 59 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies; 60 temp->when_alloc = jiffies;
65 temp->ses = ses;
66 temp->tsk = current; 61 temp->tsk = current;
67 } 62 }
68 63
69 spin_lock(&GlobalMid_Lock); 64 spin_lock(&GlobalMid_Lock);
70 list_add_tail(&temp->qhead, &ses->server->pending_mid_q); 65 list_add_tail(&temp->qhead, &server->pending_mid_q);
71 atomic_inc(&midCount); 66 atomic_inc(&midCount);
72 temp->midState = MID_REQUEST_ALLOCATED; 67 temp->midState = MID_REQUEST_ALLOCATED;
73 spin_unlock(&GlobalMid_Lock); 68 spin_unlock(&GlobalMid_Lock);
@@ -349,37 +344,38 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
349 if (long_op == CIFS_ASYNC_OP) { 344 if (long_op == CIFS_ASYNC_OP) {
350 /* oplock breaks must not be held up */ 345 /* oplock breaks must not be held up */
351 atomic_inc(&ses->server->inFlight); 346 atomic_inc(&ses->server->inFlight);
352 } else { 347 return 0;
353 spin_lock(&GlobalMid_Lock); 348 }
354 while (1) { 349
355 if (atomic_read(&ses->server->inFlight) >= 350 spin_lock(&GlobalMid_Lock);
356 cifs_max_pending){ 351 while (1) {
357 spin_unlock(&GlobalMid_Lock); 352 if (atomic_read(&ses->server->inFlight) >=
353 cifs_max_pending){
354 spin_unlock(&GlobalMid_Lock);
358#ifdef CONFIG_CIFS_STATS2 355#ifdef CONFIG_CIFS_STATS2
359 atomic_inc(&ses->server->num_waiters); 356 atomic_inc(&ses->server->num_waiters);
360#endif 357#endif
361 wait_event(ses->server->request_q, 358 wait_event(ses->server->request_q,
362 atomic_read(&ses->server->inFlight) 359 atomic_read(&ses->server->inFlight)
363 < cifs_max_pending); 360 < cifs_max_pending);
364#ifdef CONFIG_CIFS_STATS2 361#ifdef CONFIG_CIFS_STATS2
365 atomic_dec(&ses->server->num_waiters); 362 atomic_dec(&ses->server->num_waiters);
366#endif 363#endif
367 spin_lock(&GlobalMid_Lock); 364 spin_lock(&GlobalMid_Lock);
368 } else { 365 } else {
369 if (ses->server->tcpStatus == CifsExiting) { 366 if (ses->server->tcpStatus == CifsExiting) {
370 spin_unlock(&GlobalMid_Lock);
371 return -ENOENT;
372 }
373
374 /* can not count locking commands against total
375 as they are allowed to block on server */
376
377 /* update # of requests on the wire to server */
378 if (long_op != CIFS_BLOCKING_OP)
379 atomic_inc(&ses->server->inFlight);
380 spin_unlock(&GlobalMid_Lock); 367 spin_unlock(&GlobalMid_Lock);
381 break; 368 return -ENOENT;
382 } 369 }
370
371 /* can not count locking commands against total
372 as they are allowed to block on server */
373
374 /* update # of requests on the wire to server */
375 if (long_op != CIFS_BLOCKING_OP)
376 atomic_inc(&ses->server->inFlight);
377 spin_unlock(&GlobalMid_Lock);
378 break;
383 } 379 }
384 } 380 }
385 return 0; 381 return 0;
@@ -390,17 +386,21 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
390{ 386{
391 if (ses->server->tcpStatus == CifsExiting) { 387 if (ses->server->tcpStatus == CifsExiting) {
392 return -ENOENT; 388 return -ENOENT;
393 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 389 }
390
391 if (ses->server->tcpStatus == CifsNeedReconnect) {
394 cFYI(1, ("tcp session dead - return to caller to retry")); 392 cFYI(1, ("tcp session dead - return to caller to retry"));
395 return -EAGAIN; 393 return -EAGAIN;
396 } else if (ses->status != CifsGood) { 394 }
395
396 if (ses->status != CifsGood) {
397 /* check if SMB session is bad because we are setting it up */ 397 /* check if SMB session is bad because we are setting it up */
398 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 398 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
399 (in_buf->Command != SMB_COM_NEGOTIATE)) 399 (in_buf->Command != SMB_COM_NEGOTIATE))
400 return -EAGAIN; 400 return -EAGAIN;
401 /* else ok - we are setting up session */ 401 /* else ok - we are setting up session */
402 } 402 }
403 *ppmidQ = AllocMidQEntry(in_buf, ses); 403 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
404 if (*ppmidQ == NULL) 404 if (*ppmidQ == NULL)
405 return -ENOMEM; 405 return -ENOMEM;
406 return 0; 406 return 0;
@@ -415,11 +415,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
415 415
416 for (;;) { 416 for (;;) {
417 curr_timeout = timeout + jiffies; 417 curr_timeout = timeout + jiffies;
418 wait_event(ses->server->response_q, 418 wait_event_timeout(ses->server->response_q,
419 (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 419 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
420 time_after(jiffies, curr_timeout) ||
421 ((ses->server->tcpStatus != CifsGood) &&
422 (ses->server->tcpStatus != CifsNew)));
423 420
424 if (time_after(jiffies, curr_timeout) && 421 if (time_after(jiffies, curr_timeout) &&
425 (midQ->midState == MID_REQUEST_SUBMITTED) && 422 (midQ->midState == MID_REQUEST_SUBMITTED) &&
@@ -521,11 +518,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
521 and avoid races inside tcp sendmsg code that could cause corruption 518 and avoid races inside tcp sendmsg code that could cause corruption
522 of smb data */ 519 of smb data */
523 520
524 down(&ses->server->tcpSem); 521 mutex_lock(&ses->server->srv_mutex);
525 522
526 rc = allocate_mid(ses, in_buf, &midQ); 523 rc = allocate_mid(ses, in_buf, &midQ);
527 if (rc) { 524 if (rc) {
528 up(&ses->server->tcpSem); 525 mutex_unlock(&ses->server->srv_mutex);
529 cifs_small_buf_release(in_buf); 526 cifs_small_buf_release(in_buf);
530 /* Update # of requests on wire to server */ 527 /* Update # of requests on wire to server */
531 atomic_dec(&ses->server->inFlight); 528 atomic_dec(&ses->server->inFlight);
@@ -533,6 +530,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
533 return rc; 530 return rc;
534 } 531 }
535 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 532 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
533 if (rc) {
534 mutex_unlock(&ses->server->srv_mutex);
535 cifs_small_buf_release(in_buf);
536 goto out;
537 }
536 538
537 midQ->midState = MID_REQUEST_SUBMITTED; 539 midQ->midState = MID_REQUEST_SUBMITTED;
538#ifdef CONFIG_CIFS_STATS2 540#ifdef CONFIG_CIFS_STATS2
@@ -546,7 +548,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
546 midQ->when_sent = jiffies; 548 midQ->when_sent = jiffies;
547#endif 549#endif
548 550
549 up(&ses->server->tcpSem); 551 mutex_unlock(&ses->server->srv_mutex);
550 cifs_small_buf_release(in_buf); 552 cifs_small_buf_release(in_buf);
551 553
552 if (rc < 0) 554 if (rc < 0)
@@ -581,10 +583,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
581 wait_for_response(ses, midQ, timeout, 10 * HZ); 583 wait_for_response(ses, midQ, timeout, 10 * HZ);
582 584
583 spin_lock(&GlobalMid_Lock); 585 spin_lock(&GlobalMid_Lock);
584 if (midQ->resp_buf) { 586
585 spin_unlock(&GlobalMid_Lock); 587 if (midQ->resp_buf == NULL) {
586 receive_len = midQ->resp_buf->smb_buf_length;
587 } else {
588 cERROR(1, ("No response to cmd %d mid %d", 588 cERROR(1, ("No response to cmd %d mid %d",
589 midQ->command, midQ->mid)); 589 midQ->command, midQ->mid));
590 if (midQ->midState == MID_REQUEST_SUBMITTED) { 590 if (midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -612,53 +612,59 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
612 return rc; 612 return rc;
613 } 613 }
614 614
615 spin_unlock(&GlobalMid_Lock);
616 receive_len = midQ->resp_buf->smb_buf_length;
617
615 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 618 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
616 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 619 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
617 receive_len, xid)); 620 receive_len, xid));
618 rc = -EIO; 621 rc = -EIO;
619 } else { /* rcvd frame is ok */ 622 goto out;
620 if (midQ->resp_buf && 623 }
621 (midQ->midState == MID_RESPONSE_RECEIVED)) { 624
622 625 /* rcvd frame is ok */
623 iov[0].iov_base = (char *)midQ->resp_buf; 626
624 if (midQ->largeBuf) 627 if (midQ->resp_buf &&
625 *pRespBufType = CIFS_LARGE_BUFFER; 628 (midQ->midState == MID_RESPONSE_RECEIVED)) {
626 else 629
627 *pRespBufType = CIFS_SMALL_BUFFER; 630 iov[0].iov_base = (char *)midQ->resp_buf;
628 iov[0].iov_len = receive_len + 4; 631 if (midQ->largeBuf)
629 632 *pRespBufType = CIFS_LARGE_BUFFER;
630 dump_smb(midQ->resp_buf, 80); 633 else
631 /* convert the length into a more usable form */ 634 *pRespBufType = CIFS_SMALL_BUFFER;
632 if ((receive_len > 24) && 635 iov[0].iov_len = receive_len + 4;
633 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 636
634 SECMODE_SIGN_ENABLED))) { 637 dump_smb(midQ->resp_buf, 80);
635 rc = cifs_verify_signature(midQ->resp_buf, 638 /* convert the length into a more usable form */
639 if ((receive_len > 24) &&
640 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
641 SECMODE_SIGN_ENABLED))) {
642 rc = cifs_verify_signature(midQ->resp_buf,
636 &ses->server->mac_signing_key, 643 &ses->server->mac_signing_key,
637 midQ->sequence_number+1); 644 midQ->sequence_number+1);
638 if (rc) { 645 if (rc) {
639 cERROR(1, ("Unexpected SMB signature")); 646 cERROR(1, ("Unexpected SMB signature"));
640 /* BB FIXME add code to kill session */ 647 /* BB FIXME add code to kill session */
641 }
642 } 648 }
643
644 /* BB special case reconnect tid and uid here? */
645 rc = map_smb_to_linux_error(midQ->resp_buf,
646 flags & CIFS_LOG_ERROR);
647
648 /* convert ByteCount if necessary */
649 if (receive_len >= sizeof(struct smb_hdr) - 4
650 /* do not count RFC1001 header */ +
651 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
652 BCC(midQ->resp_buf) =
653 le16_to_cpu(BCC_LE(midQ->resp_buf));
654 if ((flags & CIFS_NO_RESP) == 0)
655 midQ->resp_buf = NULL; /* mark it so buf will
656 not be freed by
657 DeleteMidQEntry */
658 } else {
659 rc = -EIO;
660 cFYI(1, ("Bad MID state?"));
661 } 649 }
650
651 /* BB special case reconnect tid and uid here? */
652 rc = map_smb_to_linux_error(midQ->resp_buf,
653 flags & CIFS_LOG_ERROR);
654
655 /* convert ByteCount if necessary */
656 if (receive_len >= sizeof(struct smb_hdr) - 4
657 /* do not count RFC1001 header */ +
658 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
659 BCC(midQ->resp_buf) =
660 le16_to_cpu(BCC_LE(midQ->resp_buf));
661 if ((flags & CIFS_NO_RESP) == 0)
662 midQ->resp_buf = NULL; /* mark it so buf will
663 not be freed by
664 DeleteMidQEntry */
665 } else {
666 rc = -EIO;
667 cFYI(1, ("Bad MID state?"));
662 } 668 }
663 669
664out: 670out:
@@ -695,6 +701,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
695 to the same server. We may make this configurable later or 701 to the same server. We may make this configurable later or
696 use ses->maxReq */ 702 use ses->maxReq */
697 703
704 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
705 cERROR(1, ("Illegal length, greater than maximum frame, %d",
706 in_buf->smb_buf_length));
707 return -EIO;
708 }
709
698 rc = wait_for_free_request(ses, long_op); 710 rc = wait_for_free_request(ses, long_op);
699 if (rc) 711 if (rc)
700 return rc; 712 return rc;
@@ -703,29 +715,22 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
703 and avoid races inside tcp sendmsg code that could cause corruption 715 and avoid races inside tcp sendmsg code that could cause corruption
704 of smb data */ 716 of smb data */
705 717
706 down(&ses->server->tcpSem); 718 mutex_lock(&ses->server->srv_mutex);
707 719
708 rc = allocate_mid(ses, in_buf, &midQ); 720 rc = allocate_mid(ses, in_buf, &midQ);
709 if (rc) { 721 if (rc) {
710 up(&ses->server->tcpSem); 722 mutex_unlock(&ses->server->srv_mutex);
711 /* Update # of requests on wire to server */ 723 /* Update # of requests on wire to server */
712 atomic_dec(&ses->server->inFlight); 724 atomic_dec(&ses->server->inFlight);
713 wake_up(&ses->server->request_q); 725 wake_up(&ses->server->request_q);
714 return rc; 726 return rc;
715 } 727 }
716 728
717 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
718 cERROR(1, ("Illegal length, greater than maximum frame, %d",
719 in_buf->smb_buf_length));
720 DeleteMidQEntry(midQ);
721 up(&ses->server->tcpSem);
722 /* Update # of requests on wire to server */
723 atomic_dec(&ses->server->inFlight);
724 wake_up(&ses->server->request_q);
725 return -EIO;
726 }
727
728 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 729 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
730 if (rc) {
731 mutex_unlock(&ses->server->srv_mutex);
732 goto out;
733 }
729 734
730 midQ->midState = MID_REQUEST_SUBMITTED; 735 midQ->midState = MID_REQUEST_SUBMITTED;
731#ifdef CONFIG_CIFS_STATS2 736#ifdef CONFIG_CIFS_STATS2
@@ -738,7 +743,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
738 atomic_dec(&ses->server->inSend); 743 atomic_dec(&ses->server->inSend);
739 midQ->when_sent = jiffies; 744 midQ->when_sent = jiffies;
740#endif 745#endif
741 up(&ses->server->tcpSem); 746 mutex_unlock(&ses->server->srv_mutex);
742 747
743 if (rc < 0) 748 if (rc < 0)
744 goto out; 749 goto out;
@@ -772,10 +777,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
772 wait_for_response(ses, midQ, timeout, 10 * HZ); 777 wait_for_response(ses, midQ, timeout, 10 * HZ);
773 778
774 spin_lock(&GlobalMid_Lock); 779 spin_lock(&GlobalMid_Lock);
775 if (midQ->resp_buf) { 780 if (midQ->resp_buf == NULL) {
776 spin_unlock(&GlobalMid_Lock);
777 receive_len = midQ->resp_buf->smb_buf_length;
778 } else {
779 cERROR(1, ("No response for cmd %d mid %d", 781 cERROR(1, ("No response for cmd %d mid %d",
780 midQ->command, midQ->mid)); 782 midQ->command, midQ->mid));
781 if (midQ->midState == MID_REQUEST_SUBMITTED) { 783 if (midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -803,47 +805,52 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
803 return rc; 805 return rc;
804 } 806 }
805 807
808 spin_unlock(&GlobalMid_Lock);
809 receive_len = midQ->resp_buf->smb_buf_length;
810
806 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 811 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
807 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 812 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
808 receive_len, xid)); 813 receive_len, xid));
809 rc = -EIO; 814 rc = -EIO;
810 } else { /* rcvd frame is ok */ 815 goto out;
811 816 }
812 if (midQ->resp_buf && out_buf 817
813 && (midQ->midState == MID_RESPONSE_RECEIVED)) { 818 /* rcvd frame is ok */
814 out_buf->smb_buf_length = receive_len; 819
815 memcpy((char *)out_buf + 4, 820 if (midQ->resp_buf && out_buf
816 (char *)midQ->resp_buf + 4, 821 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
817 receive_len); 822 out_buf->smb_buf_length = receive_len;
818 823 memcpy((char *)out_buf + 4,
819 dump_smb(out_buf, 92); 824 (char *)midQ->resp_buf + 4,
820 /* convert the length into a more usable form */ 825 receive_len);
821 if ((receive_len > 24) && 826
822 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 827 dump_smb(out_buf, 92);
823 SECMODE_SIGN_ENABLED))) { 828 /* convert the length into a more usable form */
824 rc = cifs_verify_signature(out_buf, 829 if ((receive_len > 24) &&
830 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
831 SECMODE_SIGN_ENABLED))) {
832 rc = cifs_verify_signature(out_buf,
825 &ses->server->mac_signing_key, 833 &ses->server->mac_signing_key,
826 midQ->sequence_number+1); 834 midQ->sequence_number+1);
827 if (rc) { 835 if (rc) {
828 cERROR(1, ("Unexpected SMB signature")); 836 cERROR(1, ("Unexpected SMB signature"));
829 /* BB FIXME add code to kill session */ 837 /* BB FIXME add code to kill session */
830 }
831 } 838 }
839 }
832 840
833 *pbytes_returned = out_buf->smb_buf_length; 841 *pbytes_returned = out_buf->smb_buf_length;
834 842
835 /* BB special case reconnect tid and uid here? */ 843 /* BB special case reconnect tid and uid here? */
836 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); 844 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
837 845
838 /* convert ByteCount if necessary */ 846 /* convert ByteCount if necessary */
839 if (receive_len >= sizeof(struct smb_hdr) - 4 847 if (receive_len >= sizeof(struct smb_hdr) - 4
840 /* do not count RFC1001 header */ + 848 /* do not count RFC1001 header */ +
841 (2 * out_buf->WordCount) + 2 /* bcc */ ) 849 (2 * out_buf->WordCount) + 2 /* bcc */ )
842 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 850 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
843 } else { 851 } else {
844 rc = -EIO; 852 rc = -EIO;
845 cERROR(1, ("Bad MID state?")); 853 cERROR(1, ("Bad MID state?"));
846 }
847 } 854 }
848 855
849out: 856out:
@@ -866,16 +873,16 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
866 873
867 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); 874 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
868 in_buf->Mid = mid; 875 in_buf->Mid = mid;
869 down(&ses->server->tcpSem); 876 mutex_lock(&ses->server->srv_mutex);
870 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 877 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
871 if (rc) { 878 if (rc) {
872 up(&ses->server->tcpSem); 879 mutex_unlock(&ses->server->srv_mutex);
873 return rc; 880 return rc;
874 } 881 }
875 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 882 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
876 (struct sockaddr *) &(ses->server->addr.sockAddr), 883 (struct sockaddr *) &(ses->server->addr.sockAddr),
877 ses->server->noblocksnd); 884 ses->server->noblocksnd);
878 up(&ses->server->tcpSem); 885 mutex_unlock(&ses->server->srv_mutex);
879 return rc; 886 return rc;
880} 887}
881 888
@@ -933,6 +940,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
933 to the same server. We may make this configurable later or 940 to the same server. We may make this configurable later or
934 use ses->maxReq */ 941 use ses->maxReq */
935 942
943 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
944 cERROR(1, ("Illegal length, greater than maximum frame, %d",
945 in_buf->smb_buf_length));
946 return -EIO;
947 }
948
936 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); 949 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
937 if (rc) 950 if (rc)
938 return rc; 951 return rc;
@@ -941,24 +954,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
941 and avoid races inside tcp sendmsg code that could cause corruption 954 and avoid races inside tcp sendmsg code that could cause corruption
942 of smb data */ 955 of smb data */
943 956
944 down(&ses->server->tcpSem); 957 mutex_lock(&ses->server->srv_mutex);
945 958
946 rc = allocate_mid(ses, in_buf, &midQ); 959 rc = allocate_mid(ses, in_buf, &midQ);
947 if (rc) { 960 if (rc) {
948 up(&ses->server->tcpSem); 961 mutex_unlock(&ses->server->srv_mutex);
949 return rc; 962 return rc;
950 } 963 }
951 964
952 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 965 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
953 up(&ses->server->tcpSem); 966 if (rc) {
954 cERROR(1, ("Illegal length, greater than maximum frame, %d",
955 in_buf->smb_buf_length));
956 DeleteMidQEntry(midQ); 967 DeleteMidQEntry(midQ);
957 return -EIO; 968 mutex_unlock(&ses->server->srv_mutex);
969 return rc;
958 } 970 }
959 971
960 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
961
962 midQ->midState = MID_REQUEST_SUBMITTED; 972 midQ->midState = MID_REQUEST_SUBMITTED;
963#ifdef CONFIG_CIFS_STATS2 973#ifdef CONFIG_CIFS_STATS2
964 atomic_inc(&ses->server->inSend); 974 atomic_inc(&ses->server->inSend);
@@ -970,7 +980,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
970 atomic_dec(&ses->server->inSend); 980 atomic_dec(&ses->server->inSend);
971 midQ->when_sent = jiffies; 981 midQ->when_sent = jiffies;
972#endif 982#endif
973 up(&ses->server->tcpSem); 983 mutex_unlock(&ses->server->srv_mutex);
974 984
975 if (rc < 0) { 985 if (rc < 0) {
976 DeleteMidQEntry(midQ); 986 DeleteMidQEntry(midQ);
@@ -1052,44 +1062,48 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
1052 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 1062 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1053 receive_len, xid)); 1063 receive_len, xid));
1054 rc = -EIO; 1064 rc = -EIO;
1055 } else { /* rcvd frame is ok */ 1065 goto out;
1056 1066 }
1057 if (midQ->resp_buf && out_buf
1058 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1059 out_buf->smb_buf_length = receive_len;
1060 memcpy((char *)out_buf + 4,
1061 (char *)midQ->resp_buf + 4,
1062 receive_len);
1063
1064 dump_smb(out_buf, 92);
1065 /* convert the length into a more usable form */
1066 if ((receive_len > 24) &&
1067 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1068 SECMODE_SIGN_ENABLED))) {
1069 rc = cifs_verify_signature(out_buf,
1070 &ses->server->mac_signing_key,
1071 midQ->sequence_number+1);
1072 if (rc) {
1073 cERROR(1, ("Unexpected SMB signature"));
1074 /* BB FIXME add code to kill session */
1075 }
1076 }
1077 1067
1078 *pbytes_returned = out_buf->smb_buf_length; 1068 /* rcvd frame is ok */
1079 1069
1080 /* BB special case reconnect tid and uid here? */ 1070 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
1081 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); 1071 rc = -EIO;
1072 cERROR(1, ("Bad MID state?"));
1073 goto out;
1074 }
1082 1075
1083 /* convert ByteCount if necessary */ 1076 out_buf->smb_buf_length = receive_len;
1084 if (receive_len >= sizeof(struct smb_hdr) - 4 1077 memcpy((char *)out_buf + 4,
1085 /* do not count RFC1001 header */ + 1078 (char *)midQ->resp_buf + 4,
1086 (2 * out_buf->WordCount) + 2 /* bcc */ ) 1079 receive_len);
1087 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 1080
1088 } else { 1081 dump_smb(out_buf, 92);
1089 rc = -EIO; 1082 /* convert the length into a more usable form */
1090 cERROR(1, ("Bad MID state?")); 1083 if ((receive_len > 24) &&
1084 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1085 SECMODE_SIGN_ENABLED))) {
1086 rc = cifs_verify_signature(out_buf,
1087 &ses->server->mac_signing_key,
1088 midQ->sequence_number+1);
1089 if (rc) {
1090 cERROR(1, ("Unexpected SMB signature"));
1091 /* BB FIXME add code to kill session */
1091 } 1092 }
1092 } 1093 }
1094
1095 *pbytes_returned = out_buf->smb_buf_length;
1096
1097 /* BB special case reconnect tid and uid here? */
1098 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1099
1100 /* convert ByteCount if necessary */
1101 if (receive_len >= sizeof(struct smb_hdr) - 4
1102 /* do not count RFC1001 header */ +
1103 (2 * out_buf->WordCount) + 2 /* bcc */ )
1104 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1105
1106out:
1093 DeleteMidQEntry(midQ); 1107 DeleteMidQEntry(midQ);
1094 if (rstart && rc == -EACCES) 1108 if (rstart && rc == -EACCES)
1095 return -ERESTARTSYS; 1109 return -ERESTARTSYS;