[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>
This commit is contained in:
parent
adddd49ddf
commit
c18c732ec6
|
@ -10,7 +10,8 @@ opened, read and written as if they were files). When 1st tree
|
||||||
connect fails (e.g. due to signing negotiation failure) fix
|
connect fails (e.g. due to signing negotiation failure) fix
|
||||||
leak that causes cifsd not to stop and rmmod to fail to cleanup
|
leak that causes cifsd not to stop and rmmod to fail to cleanup
|
||||||
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
|
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
|
||||||
bigendian architectures.
|
bigendian architectures. Fix possible memory corruption when
|
||||||
|
EAGAIN returned on kern_recvmsg.
|
||||||
|
|
||||||
Version 1.50
|
Version 1.50
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -415,6 +415,9 @@ incomplete_rcv:
|
||||||
msleep(1); /* minimum sleep to prevent looping
|
msleep(1); /* minimum sleep to prevent looping
|
||||||
allowing socket to clear and app threads to set
|
allowing socket to clear and app threads to set
|
||||||
tcpStatus CifsNeedReconnect if server hung */
|
tcpStatus CifsNeedReconnect if server hung */
|
||||||
|
if (pdu_length < 4)
|
||||||
|
goto incomplete_rcv;
|
||||||
|
else
|
||||||
continue;
|
continue;
|
||||||
} else if (length <= 0) {
|
} else if (length <= 0) {
|
||||||
if (server->tcpStatus == CifsNew) {
|
if (server->tcpStatus == CifsNew) {
|
||||||
|
@ -543,6 +546,7 @@ incomplete_rcv:
|
||||||
allowing socket to clear and app
|
allowing socket to clear and app
|
||||||
threads to set tcpStatus
|
threads to set tcpStatus
|
||||||
CifsNeedReconnect if server hung*/
|
CifsNeedReconnect if server hung*/
|
||||||
|
length = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if (length <= 0) {
|
} else if (length <= 0) {
|
||||||
cERROR(1, ("Received no data, expecting %d",
|
cERROR(1, ("Received no data, expecting %d",
|
||||||
|
|
Loading…
Reference in New Issue