|
From: <sv...@va...> - 2016-10-01 11:54:53
|
Author: mjw
Date: Sat Oct 1 12:54:47 2016
New Revision: 15992
Log:
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.
Modified:
trunk/NEWS
trunk/coregrind/m_syswrap/syswrap-linux.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sat Oct 1 12:54:47 2016
@@ -182,6 +182,7 @@
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
Modified: trunk/coregrind/m_syswrap/syswrap-linux.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-linux.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-linux.c Sat Oct 1 12:54:47 2016
@@ -3408,8 +3408,23 @@
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*/,
|