From d7d8231750da44d90116e00858868ca4065634d9 Mon Sep 17 00:00:00 2001 From: Philippe Waroquiers Date: Sat, 12 Jan 2019 15:08:59 +0100 Subject: [PATCH] Fix false positive 'Conditional jump or move' on amd64 64 bits ptracing 32 bits. PTRACE_GET_THREAD_AREA is not handled by amd64 linux syswrap, which leads to false positive errors in 64 bits program ptrace-ing 32 bits processes. For example, the below error was wrongly reported on GDB: ==25377== Conditional jump or move depends on uninitialised value(s) ==25377== at 0x8A1D7EC: td_thr_get_info (td_thr_get_info.c:35) ==25377== by 0x526819: thread_from_lwp(thread_info*, ptid_t) (linux-thread-db.c:417) ==25377== by 0x5281D4: thread_db_notice_clone(ptid_t, ptid_t) (linux-thread-db.c:442) ==25377== by 0x51773B: linux_handle_extended_wait(lwp_info*, int) (linux-nat.c:2027) .... ==25377== Uninitialised value was created by a stack allocation ==25377== at 0x69A360: x86_linux_get_thread_area(int, void*, unsigned int*) (x86-linux-nat.c:278) Fix this by implementing PTRACE_GET|SET_THREAD_AREA on amd64. --- NEWS | 2 ++ coregrind/m_syswrap/syswrap-amd64-linux.c | 11 +++++++++++ include/vki/vki-amd64-linux.h | 20 ++++++++++++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 2d1f2e99b9..6ff9464238 100644 --- a/NEWS +++ b/NEWS @@ -86,6 +86,8 @@ where XXXXXX is the bug number as listed below. 402515 Implement new option --show-error-list=no|yes / -s 402519 POWER 3.0 addex instruction incorrectly implemented +n-i-bz add syswrap for PTRACE_GET|SET_THREAD_AREA on amd64. + Release 3.14.0 (9 October 2018) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 60fb5ffc08..30e7d0e910 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -322,6 +322,10 @@ PRE(sys_ptrace) PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4, sizeof (struct vki_user_i387_struct)); break; + case VKI_PTRACE_GET_THREAD_AREA: + PRE_MEM_WRITE( "ptrace(get_thread_area)", ARG4, + sizeof(struct vki_user_desc) ); + break; case VKI_PTRACE_SETREGS: PRE_MEM_READ( "ptrace(setregs)", ARG4, sizeof (struct vki_user_regs_struct)); @@ -330,6 +334,10 @@ PRE(sys_ptrace) PRE_MEM_READ( "ptrace(setfpregs)", ARG4, sizeof (struct vki_user_i387_struct)); break; + case VKI_PTRACE_SET_THREAD_AREA: + PRE_MEM_READ( "ptrace(set_thread_area)", ARG4, + sizeof(struct vki_user_desc) ); + break; case VKI_PTRACE_GETEVENTMSG: PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long)); break; @@ -367,6 +375,9 @@ POST(sys_ptrace) case VKI_PTRACE_GETFPREGS: POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct)); break; + case VKI_PTRACE_GET_THREAD_AREA: + POST_MEM_WRITE( ARG4, sizeof(struct vki_user_desc) ); + break; case VKI_PTRACE_GETEVENTMSG: POST_MEM_WRITE( ARG4, sizeof(unsigned long)); break; diff --git a/include/vki/vki-amd64-linux.h b/include/vki/vki-amd64-linux.h index a506ade06c..f99dcf81cf 100644 --- a/include/vki/vki-amd64-linux.h +++ b/include/vki/vki-amd64-linux.h @@ -559,16 +559,15 @@ struct vki_ucontext { #define VKI_ARCH_GET_GS 0x1004 //---------------------------------------------------------------------- -// From linux-2.6.9/include/asm-x86_64/ldt.h +// Originally from linux-2.6.9/include/asm-x86_64/ldt.h //---------------------------------------------------------------------- -// I think this LDT stuff will have to be reinstated for amd64, but I'm not -// certain. (Nb: The sys_arch_prctl seems to have replaced -// [gs]et_thread_area syscalls.) -// // Note that the type here is very slightly different to the -// type for x86 (the final 'lm' field is added); I'm not sure about the -// significance of that... --njn +// type for x86 (the final 'lm' field is added). +/* The explanation is: the final bit is not present in 32 bit code running + on 64 bits kernel. The kernel has to assume this value is 0 whenever + user_desc arrives from a 32-bit program. + See /usr/include/asm/ldt.h. */ /* [[Nb: This is the structure passed to the modify_ldt syscall. Just so as to confuse and annoy everyone, this is _not_ the same as an @@ -579,7 +578,7 @@ struct vki_ucontext { is rather for 32bit. */ struct vki_user_desc { unsigned int entry_number; - unsigned long base_addr; + unsigned int base_addr; unsigned int limit; unsigned int seg_32bit:1; unsigned int contents:2; @@ -683,6 +682,11 @@ struct vki_shminfo64 { #define VKI_PTRACE_GETFPREGS 14 #define VKI_PTRACE_SETFPREGS 15 +// From /usr/include/asm/ptrace-abit.h +/* only useful for access 32bit programs / kernels */ +#define VKI_PTRACE_GET_THREAD_AREA 25 +#define VKI_PTRACE_SET_THREAD_AREA 26 + //---------------------------------------------------------------------- // From linux-2.6.8.1/include/asm-generic/errno.h //---------------------------------------------------------------------- -- 2.47.2