aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2007-10-17 14:01:11 -0400
committerSteve French <sfrench@us.ibm.com>2007-10-17 14:01:11 -0400
commitc18c732ec6bf372aa959ca6534cbfc32e464defd (patch)
treeee6ea1110cb83ea552f6f3281f76239b7597c224 /fs/cifs/connect.c
parentadddd49ddf4ce5a5997f0695b194587290ea72e9 (diff)
[CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread
When kernel_recvmsg returns -EAGAIN or -ERESTARTSYS, then cifs_demultiplex_thread sleeps for a bit and then tries the read again. When it does this, it's not zeroing out the length and that throws off the value of total_read. Fix it to zero out the length. Can cause memory corruption: If kernel_recvmsg returns an error and total_read is a large enough value, then we'll end up going through the loop again. total_read will be a bogus value, as will (pdu_length-total_read). When this happens we end up calling kernel_recvmsg with a bogus value (possibly larger than the current iov_len). At that point, memcpy_toiovec can overrun iov. It will start walking up the stack, casting other things that are there to struct iovecs (since it assumes that it's been passed an array of them). Any pointer on the stack at an address above the kvec is a candidate for corruption here. Many thanks to Ulrich Obergfell for pointing this out. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 494455ed4352..676bbf2bb56d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -415,7 +415,10 @@ incomplete_rcv:
415 msleep(1); /* minimum sleep to prevent looping 415 msleep(1); /* minimum sleep to prevent looping
416 allowing socket to clear and app threads to set 416 allowing socket to clear and app threads to set
417 tcpStatus CifsNeedReconnect if server hung */ 417 tcpStatus CifsNeedReconnect if server hung */
418 continue; 418 if (pdu_length < 4)
419 goto incomplete_rcv;
420 else
421 continue;
419 } else if (length <= 0) { 422 } else if (length <= 0) {
420 if (server->tcpStatus == CifsNew) { 423 if (server->tcpStatus == CifsNew) {
421 cFYI(1, ("tcp session abend after SMBnegprot")); 424 cFYI(1, ("tcp session abend after SMBnegprot"));
@@ -543,6 +546,7 @@ incomplete_rcv:
543 allowing socket to clear and app 546 allowing socket to clear and app
544 threads to set tcpStatus 547 threads to set tcpStatus
545 CifsNeedReconnect if server hung*/ 548 CifsNeedReconnect if server hung*/
549 length = 0;
546 continue; 550 continue;
547 } else if (length <= 0) { 551 } else if (length <= 0) {
548 cERROR(1, ("Received no data, expecting %d", 552 cERROR(1, ("Received no data, expecting %d",