[msan] Intercept fopencookie.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Fri, 19 Jun 2015 01:28:41 +0000 (01:28 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Fri, 19 Jun 2015 01:28:41 +0000 (01:28 +0000)
https://code.google.com/p/memory-sanitizer/issues/detail?id=86

llvm-svn: 240107

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
compiler-rt/test/msan/Linux/fopencookie.cc [new file with mode: 0644]

index ee21ccf..9b75a30 100644 (file)
@@ -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;
 }
index 8142be5..9bb15d7 100644 (file)
 #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
index e8117f3..cbfb03c 100644 (file)
@@ -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
index 77bbdb1..cba876d 100644 (file)
@@ -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 (file)
index 0000000..e9616d5
--- /dev/null
@@ -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 <assert.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sanitizer/msan_interface.h>
+
+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);
+}