From: Mark Wielaard Date: Sat, 1 Oct 2016 11:54:47 +0000 (+0000) Subject: Fix crash when old/new sigprocmask isn't safe to dereference. Bug #369360. X-Git-Tag: svn/VALGRIND_3_13_0~374 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52b55f29f37accd5bc2ea33169fc296d1edfc5d6;p=thirdparty%2Fvalgrind.git Fix crash when old/new sigprocmask isn't safe to dereference. Bug #369360. Since we want to use the set and oldset for bookkeeping we also want to make sure they are addressable otherwise, like the kernel, we EFAULT. Also use EINVAL instead of EMFILE as failure when sigset size is wrong. Found by LTP testcases/kernel/syscalls/rt_sigprocmask/rt_sigprocmask02. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15992 --- diff --git a/NEWS b/NEWS index d8c1c869e3..fca22bed0b 100644 --- a/NEWS +++ b/NEWS @@ -182,6 +182,7 @@ where XXXXXX is the bug number as listed below. 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 +369360 Bad sigprocmask old or new sets can crash valgrind 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-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 36fadbba8c..797448427a 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -3408,8 +3408,23 @@ PRE(sys_rt_sigprocmask) PRE_MEM_WRITE( "rt_sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t)); // Like the kernel, we fail if the sigsetsize is not exactly what we expect. + // Since we want to use the set and oldset for bookkeeping we also want + // to make sure they are addressable otherwise, like the kernel, we EFAULT. if (sizeof(vki_sigset_t) != ARG4) - SET_STATUS_Failure( VKI_EMFILE ); + SET_STATUS_Failure( VKI_EINVAL ); + else if (ARG2 != 0 + && ! ML_(safe_to_deref)((void *)ARG2, sizeof(vki_sigset_t))) { + VG_(dmsg)("Warning: Bad set handler address %p in sigprocmask\n", + (void *)ARG2); + SET_STATUS_Failure ( VKI_EFAULT ); + } + else if (ARG3 != 0 + && ! ML_(safe_to_deref)((void *)ARG3, sizeof(vki_sigset_t))) { + VG_(dmsg)("Warning: Bad oldset address %p in sigprocmask\n", + (void *)ARG3); + SET_STATUS_Failure ( VKI_EFAULT ); + } + else { SET_STATUS_from_SysRes( VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/,