From 791a7e1603106fe37070492774fa62d832faab9b Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 10 Feb 2014 09:37:03 +0000 Subject: [PATCH] [msan] Return EINVAL instead of crashing from mmap of an invalid address. llvm-svn: 201074 --- compiler-rt/lib/msan/lit_tests/mmap_below_shadow.cc | 16 ++++++++++------ compiler-rt/lib/msan/msan_interceptors.cc | 13 ++++++++----- .../sanitizer_common/sanitizer_platform_limits_posix.cc | 1 + .../sanitizer_common/sanitizer_platform_limits_posix.h | 1 + 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/compiler-rt/lib/msan/lit_tests/mmap_below_shadow.cc b/compiler-rt/lib/msan/lit_tests/mmap_below_shadow.cc index 215311e..0e94cef 100644 --- a/compiler-rt/lib/msan/lit_tests/mmap_below_shadow.cc +++ b/compiler-rt/lib/msan/lit_tests/mmap_below_shadow.cc @@ -1,22 +1,26 @@ // Test mmap behavior when map address is below shadow range. -// With MAP_FIXED, we crash. +// With MAP_FIXED, we return EINVAL. // Without MAP_FIXED, we ignore the address hint and map somewhere in // application range. // RUN: %clangxx_msan -m64 -O0 -DFIXED=0 %s -o %t && %t -// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 %s -o %t && not %t +// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 %s -o %t && %t #include +#include #include #include int main(void) { // Hint address just below shadow. - uintptr_t hint = 0x1f0000000000ULL; + uintptr_t hint = 0x4f0000000000ULL; const uintptr_t app_start = 0x600000000000ULL; uintptr_t p = (uintptr_t)mmap( - (void *)hint, 4096, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | (FIXED ? MAP_FIXED : 0), 0, 0); - assert(p >= app_start); + (void *)hint, 4096, PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | (FIXED ? MAP_FIXED : 0), -1, 0); + if (FIXED) + assert(p == (uintptr_t)-1 && errno == EINVAL); + else + assert(p >= app_start); return 0; } diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index cb0b1a0..d68e469 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -42,6 +42,8 @@ static unsigned g_thread_finalize_key; // True if this is a nested interceptor. static THREADLOCAL int in_interceptor_scope; +extern "C" int *__errno_location(void); + struct InterceptorScope { InterceptorScope() { ++in_interceptor_scope; } ~InterceptorScope() { --in_interceptor_scope; } @@ -796,9 +798,12 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, int fd, OFF_T offset) { ENSURE_MSAN_INITED(); if (addr && !MEM_IS_APP(addr)) { - CHECK(!(flags & map_fixed) && - "mmap(..., MAP_FIXED) outside of application memory range."); - addr = 0; + if (flags & map_fixed) { + *__errno_location() = errno_EINVAL; + return (void *)-1; + } else { + addr = 0; + } } void *res = REAL(mmap)(addr, length, prot, flags, fd, offset); if (res != (void*)-1) @@ -1171,8 +1176,6 @@ int OnExit() { } // namespace __msan -extern "C" int *__errno_location(void); - // A version of CHECK_UNPOISONED using a saved scope value. Used in common // interceptors. #define CHECK_UNPOISONED_CTX(ctx, x, n) \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 6ba9704..83a9d76 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -769,6 +769,7 @@ namespace __sanitizer { unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL; #endif + const int errno_EINVAL = EINVAL; // EOWNERDEAD is not present in some older platforms. #if defined(EOWNERDEAD) extern const int errno_EOWNERDEAD = EOWNERDEAD; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index a726a70..744e180 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -1048,6 +1048,7 @@ namespace __sanitizer { extern unsigned IOCTL_TIOCSSERIAL; #endif + extern const int errno_EINVAL; extern const int errno_EOWNERDEAD; } // namespace __sanitizer -- 2.7.4