From: Mark Wielaard Date: Sat, 1 Oct 2016 11:54:50 +0000 (+0000) Subject: Fix crash in sys_modify_ldt wrapper on bad ptr. Bug #369383. X-Git-Tag: svn/VALGRIND_3_13_0~371 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=547abdee69578e321ff474b920cff401dee41dc2;p=thirdparty%2Fvalgrind.git Fix crash in sys_modify_ldt wrapper on bad ptr. Bug #369383. Make sure ptr is safe_to_deref if not NULL. Also fixup some corner case error return codes. We have to do that ourselves since we never actually call into the kernel. Found by LTP testcases/kernel/syscalls/modify_ldt/modify_ldt01. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15995 --- diff --git a/NEWS b/NEWS index c79e9f36dd..d0c1d43f30 100644 --- a/NEWS +++ b/NEWS @@ -185,6 +185,7 @@ where XXXXXX is the bug number as listed below. 369360 Bad sigprocmask old or new sets can crash valgrind 369361 vmsplice syscall wrapper crashes on bad iovec 369362 Bad sigaction arguments crash valgrind +369383 x86 sys_modify_ldt wrapper crashes on bad ptr 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-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 0c986cba34..0d8ff45763 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -596,24 +596,31 @@ SysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode ) static SysRes sys_modify_ldt ( ThreadId tid, Int func, void* ptr, UInt bytecount ) { - SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS ); + SysRes ret; - switch (func) { - case 0: - ret = read_ldt(tid, ptr, bytecount); - break; - case 1: - ret = write_ldt(tid, ptr, bytecount, 1); - break; - case 2: - VG_(unimplemented)("sys_modify_ldt: func == 2"); - /* god knows what this is about */ - /* ret = read_default_ldt(ptr, bytecount); */ - /*UNREACHED*/ - break; - case 0x11: - ret = write_ldt(tid, ptr, bytecount, 0); - break; + if (func != 0 && func != 1 && func != 2 && func != 0x11) { + ret = VG_(mk_SysRes_Error)( VKI_ENOSYS ); + } else if (ptr != NULL && ! ML_(safe_to_deref)(ptr, bytecount)) { + ret = VG_(mk_SysRes_Error)( VKI_EFAULT ); + } else { + switch (func) { + case 0: + ret = read_ldt(tid, ptr, bytecount); + break; + case 1: + ret = write_ldt(tid, ptr, bytecount, 1); + break; + case 2: + ret = VG_(mk_SysRes_Error)( VKI_ENOSYS ); + VG_(unimplemented)("sys_modify_ldt: func == 2"); + /* god knows what this is about */ + /* ret = read_default_ldt(ptr, bytecount); */ + /*UNREACHED*/ + break; + case 0x11: + ret = write_ldt(tid, ptr, bytecount, 0); + break; + } } return ret; }