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
This commit is contained in:
Mark Wielaard
2016-10-01 11:54:50 +00:00
parent e1e9a77564
commit 547abdee69
2 changed files with 25 additions and 17 deletions

1
NEWS
View File

@@ -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

View 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;
}