]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix crash in sys_modify_ldt wrapper on bad ptr. Bug #369383.
authorMark Wielaard <mark@klomp.org>
Sat, 1 Oct 2016 11:54:50 +0000 (11:54 +0000)
committerMark Wielaard <mark@klomp.org>
Sat, 1 Oct 2016 11:54:50 +0000 (11:54 +0000)
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

NEWS
coregrind/m_syswrap/syswrap-x86-linux.c

diff --git a/NEWS b/NEWS
index c79e9f36dd638eb1d0f9aadd7340f89c4f186b6b..d0c1d43f3034d24803c5d68c2ed262a96bf5ba0a 100644 (file)
--- 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
index 0c986cba34d5f67154e70ff5dc6b95941e811270..0d8ff4576315e14acf876259a82b62a20d8ffc3b 100644 (file)
@@ -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;
 }