From: Mark Wielaard Date: Sat, 1 Oct 2016 11:54:41 +0000 (+0000) Subject: Fix crash in msghdr_foreachfield when iov_len isn't safe to dereference. X-Git-Tag: svn/VALGRIND_3_13_0~375 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e3852e27cf5d11cb7625cf1c191474ad30501e6;p=thirdparty%2Fvalgrind.git Fix crash in msghdr_foreachfield when iov_len isn't safe to dereference. Also stop checking when max length of bytes have been reached. Bug #369359 Found by LTP testcases/kernel/syscalls/recvmsg/recvmsg01. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15991 --- diff --git a/NEWS b/NEWS index ae55de72f6..d8c1c869e3 100644 --- a/NEWS +++ b/NEWS @@ -181,6 +181,7 @@ where XXXXXX is the bug number as listed below. 369169 ppc64 fails jm_int_isa_2_07 test 369209 valgrind loops and eats up all memory if cwd doesn't exist. 369356 pre_mem_read_sockaddr syscall wrapper can crash with bad sockaddr +369359 msghdr_foreachfield can crash when handling bad iovec n-i-bz Fix incorrect (or infinite loop) unwind on RHEL7 x86 and amd64 n-i-bz massif --pages-as-heap=yes does not report peak caused by mmap+munmap diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index be887b1653..957a6152ce 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -1056,15 +1056,19 @@ void msghdr_foreachfield ( VG_(sprintf) ( fieldName, "(%s.msg_iov)", name ); - foreach_func ( tid, True, fieldName, - (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) ); - - for ( i = 0; i < msg->msg_iovlen; ++i, ++iov ) { - UInt iov_len = iov->iov_len <= length ? iov->iov_len : length; - VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i ); - foreach_func ( tid, False, fieldName, - (Addr)iov->iov_base, iov_len ); - length = length - iov_len; + if (ML_(safe_to_deref)(&msg->msg_iovlen, sizeof (UInt))) { + foreach_func ( tid, True, fieldName, (Addr)iov, + msg->msg_iovlen * sizeof( struct vki_iovec ) ); + + for ( i = 0; i < msg->msg_iovlen && length > 0; ++i, ++iov ) { + if (ML_(safe_to_deref)(&iov->iov_len, sizeof (UInt))) { + UInt iov_len = iov->iov_len <= length ? iov->iov_len : length; + VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i ); + foreach_func ( tid, False, fieldName, + (Addr)iov->iov_base, iov_len ); + length = length - iov_len; + } + } } }