From 3ee98e37856935ac1d79d51364df73ce00d8218e Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 29 Oct 2013 17:59:45 +0000 Subject: [sanitizer] Ptrace syscall handler. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@193633 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/msan/lit_tests/Linux/syscalls.cc | 5 +++ lib/sanitizer_common/sanitizer_common_syscalls.inc | 40 ++++++++++++++++++++-- .../sanitizer_platform_limits_posix.cc | 3 ++ .../sanitizer_platform_limits_posix.h | 3 ++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/msan/lit_tests/Linux/syscalls.cc b/lib/msan/lit_tests/Linux/syscalls.cc index 962fba3e..797832d8 100644 --- a/lib/msan/lit_tests/Linux/syscalls.cc +++ b/lib/msan/lit_tests/Linux/syscalls.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -76,6 +77,10 @@ int main(int argc, char *argv[]) { __sanitizer_syscall_post_mq_timedreceive(kFortyTwo, 5, buf, sizeof(buf), &prio, 0); assert(__msan_test_shadow(buf, sizeof(buf)) == kFortyTwo); assert(__msan_test_shadow(&prio, sizeof(prio)) == -1); + + __msan_poison(buf, sizeof(buf)); + __sanitizer_syscall_post_ptrace(0, PTRACE_PEEKUSER, kFortyTwo, 0xABCD, buf); + assert(__msan_test_shadow(buf, sizeof(buf)) == sizeof(void *)); return 0; } diff --git a/lib/sanitizer_common/sanitizer_common_syscalls.inc b/lib/sanitizer_common/sanitizer_common_syscalls.inc index 0f500d63..baa1d5be 100644 --- a/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2218,9 +2218,45 @@ PRE_SYSCALL(ni_syscall)() {} POST_SYSCALL(ni_syscall)(long res) {} -PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {} +PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { + if (data) { + if (request == ptrace_setregs) { + PRE_READ((void *)data, struct_user_regs_struct_sz); + } else if (request == ptrace_setfpregs) { + PRE_READ((void *)data, struct_user_fpregs_struct_sz); + } else if (request == ptrace_setfpxregs) { + PRE_READ((void *)data, struct_user_fpxregs_struct_sz); + } else if (request == ptrace_setsiginfo) { + PRE_READ((void *)data, siginfo_t_sz); + } else if (request == ptrace_setregset) { + __sanitizer_iovec *iov = (__sanitizer_iovec *)data; + PRE_READ(iov->iov_base, iov->iov_len); + } + } +} -POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {} +POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) { + if (res >= 0 && data) { + // Note that this is different from the interceptor in + // sanitizer_common_interceptors.inc. + // PEEK* requests return resulting values through data pointer. + if (request == ptrace_getregs) { + POST_WRITE((void *)data, struct_user_regs_struct_sz); + } else if (request == ptrace_getfpregs) { + POST_WRITE((void *)data, struct_user_fpregs_struct_sz); + } else if (request == ptrace_getfpxregs) { + POST_WRITE((void *)data, struct_user_fpxregs_struct_sz); + } else if (request == ptrace_getsiginfo) { + POST_WRITE((void *)data, siginfo_t_sz); + } else if (request == ptrace_getregset) { + __sanitizer_iovec *iov = (__sanitizer_iovec *)data; + POST_WRITE(iov->iov_base, iov->iov_len); + } else if (request == ptrace_peekdata || request == ptrace_peektext || + request == ptrace_peekuser) { + POST_WRITE((void *)data, sizeof(void *)); + } + } +} PRE_SYSCALL(add_key)(const void *_type, const void *_description, const void *_payload, long plen, long destringid) { diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index fb932bc1..8276a969 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -218,6 +218,9 @@ namespace __sanitizer { unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); #endif + int ptrace_peektext = PTRACE_PEEKTEXT; + int ptrace_peekdata = PTRACE_PEEKDATA; + int ptrace_peekuser = PTRACE_PEEKUSER; int ptrace_getregs = PTRACE_GETREGS; int ptrace_setregs = PTRACE_SETREGS; int ptrace_getfpregs = PTRACE_GETFPREGS; diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 0b38d158..6f27ba44 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -379,6 +379,9 @@ namespace __sanitizer { extern unsigned struct_user_fpregs_struct_sz; extern unsigned struct_user_fpxregs_struct_sz; + extern int ptrace_peektext; + extern int ptrace_peekdata; + extern int ptrace_peekuser; extern int ptrace_getregs; extern int ptrace_setregs; extern int ptrace_getfpregs; -- cgit v1.2.3