aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2007-11-13 17:41:37 -0500
committerSteve French <sfrench@us.ibm.com>2007-11-13 17:41:37 -0500
commit133672efbc1085f9af990bdc145e1822ea93bcf3 (patch)
treeb93b5ba3a9559d137fe7fb86f6d1a3d33189ce0b /fs/cifs/transport.c
parent9418d5dc9ba40b88737580457bf3b7c63c60ec43 (diff)
[CIFS] Fix buffer overflow if server sends corrupt response to small
request In SendReceive() function in transport.c - it memcpy's message payload into a buffer passed via out_buf param. The function assumes that all buffers are of size (CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) , unfortunately it is also called with smaller (MAX_CIFS_SMALL_BUFFER_SIZE) buffers. There are eight callers (SMB worker functions) which are primarily affected by this change: TreeDisconnect, uLogoff, Close, findClose, SetFileSize, SetFileTimes, Lock and PosixLock CC: Dave Kleikamp <shaggy@austin.ibm.com> CC: Przemyslaw Wegrzyn <czajnik@czajsoft.pl> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c91
1 files changed, 70 insertions, 21 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 7ed32b3cb781..50b623ad9320 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
308 308
309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) 309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
310{ 310{
311 if (long_op == -1) { 311 if (long_op == CIFS_ASYNC_OP) {
312 /* oplock breaks must not be held up */ 312 /* oplock breaks must not be held up */
313 atomic_inc(&ses->server->inFlight); 313 atomic_inc(&ses->server->inFlight);
314 } else { 314 } else {
@@ -337,7 +337,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
337 as they are allowed to block on server */ 337 as they are allowed to block on server */
338 338
339 /* update # of requests on the wire to server */ 339 /* update # of requests on the wire to server */
340 if (long_op < 3) 340 if (long_op != CIFS_BLOCKING_OP)
341 atomic_inc(&ses->server->inFlight); 341 atomic_inc(&ses->server->inFlight);
342 spin_unlock(&GlobalMid_Lock); 342 spin_unlock(&GlobalMid_Lock);
343 break; 343 break;
@@ -415,17 +415,48 @@ static int wait_for_response(struct cifsSesInfo *ses,
415 } 415 }
416} 416}
417 417
418
419/*
420 *
421 * Send an SMB Request. No response info (other than return code)
422 * needs to be parsed.
423 *
424 * flags indicate the type of request buffer and how long to wait
425 * and whether to log NT STATUS code (error) before mapping it to POSIX error
426 *
427 */
428int
429SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
430 struct smb_hdr *in_buf, int flags)
431{
432 int rc;
433 struct kvec iov[1];
434 int resp_buf_type;
435
436 iov[0].iov_base = (char *)in_buf;
437 iov[0].iov_len = in_buf->smb_buf_length + 4;
438 flags |= CIFS_NO_RESP;
439 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
440#ifdef CONFIG_CIFS_DEBUG2
441 cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc));
442#endif
443 return rc;
444}
445
418int 446int
419SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 447SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
420 struct kvec *iov, int n_vec, int *pRespBufType /* ret */, 448 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
421 const int long_op, const int logError) 449 const int flags)
422{ 450{
423 int rc = 0; 451 int rc = 0;
452 int long_op;
424 unsigned int receive_len; 453 unsigned int receive_len;
425 unsigned long timeout; 454 unsigned long timeout;
426 struct mid_q_entry *midQ; 455 struct mid_q_entry *midQ;
427 struct smb_hdr *in_buf = iov[0].iov_base; 456 struct smb_hdr *in_buf = iov[0].iov_base;
428 457
458 long_op = flags & CIFS_TIMEOUT_MASK;
459
429 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ 460 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
430 461
431 if ((ses == NULL) || (ses->server == NULL)) { 462 if ((ses == NULL) || (ses->server == NULL)) {
@@ -483,15 +514,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
483 if (rc < 0) 514 if (rc < 0)
484 goto out; 515 goto out;
485 516
486 if (long_op == -1) 517 if (long_op == CIFS_STD_OP)
487 goto out; 518 timeout = 15 * HZ;
488 else if (long_op == 2) /* writes past end of file can take loong time */ 519 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
489 timeout = 180 * HZ; 520 timeout = 180 * HZ;
490 else if (long_op == 1) 521 else if (long_op == CIFS_LONG_OP)
491 timeout = 45 * HZ; /* should be greater than 522 timeout = 45 * HZ; /* should be greater than
492 servers oplock break timeout (about 43 seconds) */ 523 servers oplock break timeout (about 43 seconds) */
493 else 524 else if (long_op == CIFS_ASYNC_OP)
494 timeout = 15 * HZ; 525 goto out;
526 else if (long_op == CIFS_BLOCKING_OP)
527 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
528 else {
529 cERROR(1, ("unknown timeout flag %d", long_op));
530 rc = -EIO;
531 goto out;
532 }
495 533
496 /* wait for 15 seconds or until woken up due to response arriving or 534 /* wait for 15 seconds or until woken up due to response arriving or
497 due to last connection to this server being unmounted */ 535 due to last connection to this server being unmounted */
@@ -566,7 +604,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
566 } 604 }
567 605
568 /* BB special case reconnect tid and uid here? */ 606 /* BB special case reconnect tid and uid here? */
569 rc = map_smb_to_linux_error(midQ->resp_buf, logError); 607 rc = map_smb_to_linux_error(midQ->resp_buf,
608 flags & CIFS_LOG_ERROR);
570 609
571 /* convert ByteCount if necessary */ 610 /* convert ByteCount if necessary */
572 if (receive_len >= sizeof(struct smb_hdr) - 4 611 if (receive_len >= sizeof(struct smb_hdr) - 4
@@ -574,8 +613,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
574 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) 613 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
575 BCC(midQ->resp_buf) = 614 BCC(midQ->resp_buf) =
576 le16_to_cpu(BCC_LE(midQ->resp_buf)); 615 le16_to_cpu(BCC_LE(midQ->resp_buf));
577 midQ->resp_buf = NULL; /* mark it so will not be freed 616 if ((flags & CIFS_NO_RESP) == 0)
578 by DeleteMidQEntry */ 617 midQ->resp_buf = NULL; /* mark it so buf will
618 not be freed by
619 DeleteMidQEntry */
579 } else { 620 } else {
580 rc = -EIO; 621 rc = -EIO;
581 cFYI(1, ("Bad MID state?")); 622 cFYI(1, ("Bad MID state?"));
@@ -663,17 +704,25 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
663 if (rc < 0) 704 if (rc < 0)
664 goto out; 705 goto out;
665 706
666 if (long_op == -1) 707 if (long_op == CIFS_STD_OP)
708 timeout = 15 * HZ;
709 /* wait for 15 seconds or until woken up due to response arriving or
710 due to last connection to this server being unmounted */
711 else if (long_op == CIFS_ASYNC_OP)
667 goto out; 712 goto out;
668 else if (long_op == 2) /* writes past end of file can take loong time */ 713 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
669 timeout = 180 * HZ; 714 timeout = 180 * HZ;
670 else if (long_op == 1) 715 else if (long_op == CIFS_LONG_OP)
671 timeout = 45 * HZ; /* should be greater than 716 timeout = 45 * HZ; /* should be greater than
672 servers oplock break timeout (about 43 seconds) */ 717 servers oplock break timeout (about 43 seconds) */
673 else 718 else if (long_op == CIFS_BLOCKING_OP)
674 timeout = 15 * HZ; 719 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
675 /* wait for 15 seconds or until woken up due to response arriving or 720 else {
676 due to last connection to this server being unmounted */ 721 cERROR(1, ("unknown timeout flag %d", long_op));
722 rc = -EIO;
723 goto out;
724 }
725
677 if (signal_pending(current)) { 726 if (signal_pending(current)) {
678 /* if signal pending do not hold up user for full smb timeout 727 /* if signal pending do not hold up user for full smb timeout
679 but we still give response a chance to complete */ 728 but we still give response a chance to complete */
@@ -812,7 +861,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
812 pSMB->hdr.Mid = GetNextMid(ses->server); 861 pSMB->hdr.Mid = GetNextMid(ses->server);
813 862
814 return SendReceive(xid, ses, in_buf, out_buf, 863 return SendReceive(xid, ses, in_buf, out_buf,
815 &bytes_returned, 0); 864 &bytes_returned, CIFS_STD_OP);
816} 865}
817 866
818int 867int
@@ -844,7 +893,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
844 to the same server. We may make this configurable later or 893 to the same server. We may make this configurable later or
845 use ses->maxReq */ 894 use ses->maxReq */
846 895
847 rc = wait_for_free_request(ses, 3); 896 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
848 if (rc) 897 if (rc)
849 return rc; 898 return rc;
850 899