From 9a10674079f6e2a71fdf5acedc6533fcd63fb9bd Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Fri, 19 Jun 2015 01:28:41 +0000 Subject: [PATCH] [msan] Intercept fopencookie. https://code.google.com/p/memory-sanitizer/issues/detail?id=86 llvm-svn: 240107 --- .../sanitizer_common_interceptors.inc | 56 ++++++++++++++++++++ .../sanitizer_platform_interceptors.h | 1 + .../sanitizer_platform_limits_posix.cc | 6 +++ .../sanitizer_platform_limits_posix.h | 14 +++++ compiler-rt/test/msan/Linux/fopencookie.cc | 59 ++++++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 compiler-rt/test/msan/Linux/fopencookie.cc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index ee21ccf..9b75a30 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -4956,6 +4956,61 @@ INTERCEPTOR(int, munlockall, void) { #define INIT_MLOCKX #endif // SANITIZER_INTERCEPT_MLOCKX +#if SANITIZER_INTERCEPT_FOPENCOOKIE +struct WrappedCookie { + void *real_cookie; + __sanitizer_cookie_io_functions_t real_io_funcs; +}; + +static uptr wrapped_read(void *cookie, char *buf, uptr size) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; + return wrapped_cookie->real_io_funcs.read(wrapped_cookie->real_cookie, buf, + size); +} + +static uptr wrapped_write(void *cookie, const char *buf, uptr size) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; + return wrapped_cookie->real_io_funcs.write(wrapped_cookie->real_cookie, buf, + size); +} + +static int wrapped_seek(void *cookie, u64 *offset, int whence) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset)); + WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; + return wrapped_cookie->real_io_funcs.seek(wrapped_cookie->real_cookie, offset, + whence); +} + +static int wrapped_close(void *cookie) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(1); + WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; + int res = wrapped_cookie->real_io_funcs.close(wrapped_cookie->real_cookie); + InternalFree(wrapped_cookie); + return res; +} + +INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode, + __sanitizer_cookie_io_functions_t io_funcs) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs); + WrappedCookie *wrapped_cookie = + (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie)); + wrapped_cookie->real_cookie = cookie; + wrapped_cookie->real_io_funcs = io_funcs; + __sanitizer_FILE *res = + REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write, + wrapped_seek, wrapped_close}); + return res; +} + +#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie); +#else +#define INIT_FOPENCOOKIE +#endif // SANITIZER_INTERCEPT_FOPENCOOKIE + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -5123,4 +5178,5 @@ static void InitializeCommonInterceptors() { INIT_GETPASS; INIT_TIMERFD; INIT_MLOCKX; + INIT_FOPENCOOKIE; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 8142be5..9bb15d7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -251,5 +251,6 @@ #define SANITIZER_INTERCEPT_TIMERFD SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_MLOCKX SI_NOT_WINDOWS +#define SANITIZER_INTERCEPT_FOPENCOOKIE SI_LINUX_NOT_ANDROID #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H 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 e8117f3..cbfb03c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -1204,6 +1204,12 @@ CHECK_SIZE_AND_OFFSET(obstack, chunk_size); CHECK_SIZE_AND_OFFSET(obstack, chunk); CHECK_SIZE_AND_OFFSET(obstack, object_base); CHECK_SIZE_AND_OFFSET(obstack, next_free); + +CHECK_TYPE_SIZE(cookie_io_functions_t); +CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, read); +CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, write); +CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, seek); +CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close); #endif #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC 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 77bbdb1..cba876d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -778,6 +778,20 @@ struct __sanitizer_obstack { char *next_free; uptr more_fields[7]; }; + +typedef uptr (*__sanitizer_cookie_io_read)(void *cookie, char *buf, uptr size); +typedef uptr (*__sanitizer_cookie_io_write)(void *cookie, const char *buf, + uptr size); +typedef int (*__sanitizer_cookie_io_seek)(void *cookie, u64 *offset, + int whence); +typedef int (*__sanitizer_cookie_io_close)(void *cookie); + +struct __sanitizer_cookie_io_functions_t { + __sanitizer_cookie_io_read read; + __sanitizer_cookie_io_write write; + __sanitizer_cookie_io_seek seek; + __sanitizer_cookie_io_close close; +}; #endif #define IOC_NRBITS 8 diff --git a/compiler-rt/test/msan/Linux/fopencookie.cc b/compiler-rt/test/msan/Linux/fopencookie.cc new file mode 100644 index 0000000..e9616d5 --- /dev/null +++ b/compiler-rt/test/msan/Linux/fopencookie.cc @@ -0,0 +1,59 @@ +// Test fopencookie interceptor. +// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t +// RUN: %clangxx_msan -std=c++11 -fsanitize-memory-track-origins -O0 %s -o %t && %run %t + +#include +#include +#include +#include +#include +#include + +#include + +constexpr uintptr_t kMagicCookie = 0x12345678; + +static ssize_t cookie_read(void *cookie, char *buf, size_t size) { + assert((uintptr_t)cookie == kMagicCookie); + memset(buf, 0, size); + return 0; +} + +static ssize_t cookie_write(void *cookie, const char *buf, size_t size) { + assert((uintptr_t)cookie == kMagicCookie); + __msan_check_mem_is_initialized(buf, size); + return 0; +} + +static int cookie_seek(void *cookie, off64_t *offset, int whence) { + assert((uintptr_t)cookie == kMagicCookie); + __msan_check_mem_is_initialized(offset, sizeof(*offset)); + return 0; +} + +static int cookie_close(void *cookie) { + assert((uintptr_t)cookie == kMagicCookie); + return 0; +} + +void PoisonStack() { char a[8192]; } + +void TestPoisonStack() { + // Verify that PoisonStack has poisoned the stack - otherwise this test is not + // testing anything. + char a; + assert(__msan_test_shadow(&a - 1000, 1) == 0); +} + +int main() { + void *cookie = (void *)kMagicCookie; + FILE *f = fopencookie(cookie, "rw", + {cookie_read, cookie_write, cookie_seek, cookie_close}); + PoisonStack(); + TestPoisonStack(); + fseek(f, 100, SEEK_SET); + char buf[50]; + fread(buf, 50, 1, f); + fwrite(buf, 50, 1, f); + fclose(f); +} -- 2.7.4