[compiler-rt] r250113 - [asan] Zero initialize sem_t in sem_init.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 12 14:32:30 PDT 2015


Author: eugenis
Date: Mon Oct 12 16:32:30 2015
New Revision: 250113

URL: http://llvm.org/viewvc/llvm-project?rev=250113&view=rev
Log:
[asan] Zero initialize sem_t in sem_init.

Old version of sem_init (GLIBC_2.0) fails to initialize parts of
sem_t that are used in sem_timedwait. This is fixed in GLIBC_2.1,
but since ASan interceptors downgrade sem_* to the oldest available
version, this can introduce bugs that are only present in sanitized
build. Workaround by zero-initializing sem_t in sem_init.

Added:
    compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=250113&r1=250112&r2=250113&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Mon Oct 12 16:32:30 2015
@@ -5114,21 +5114,26 @@ INTERCEPTOR(__sanitizer_FILE *, fopencoo
 #endif  // SANITIZER_INTERCEPT_FOPENCOOKIE
 
 #if SANITIZER_INTERCEPT_SEM
-INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) {
+INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
+  // Workaround a bug in glibc's "old" semaphore implementation by
+  // zero-initializing the sem_t contents. This has to be done here because
+  // interceptors bind to the lowest symbols version by default, hitting the
+  // buggy code path while the non-sanitized build of the same code works fine.
+  REAL(memset)(s, 0, sizeof(*s));
   int res = REAL(sem_init)(s, pshared, value);
   return res;
 }
 
-INTERCEPTOR(int, sem_destroy, void *s) {
+INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
   int res = REAL(sem_destroy)(s);
   return res;
 }
 
-INTERCEPTOR(int, sem_wait, void *s) {
+INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
@@ -5138,7 +5143,7 @@ INTERCEPTOR(int, sem_wait, void *s) {
   return res;
 }
 
-INTERCEPTOR(int, sem_trywait, void *s) {
+INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
@@ -5148,7 +5153,7 @@ INTERCEPTOR(int, sem_trywait, void *s) {
   return res;
 }
 
-INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
+INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
@@ -5159,7 +5164,7 @@ INTERCEPTOR(int, sem_timedwait, void *s,
   return res;
 }
 
-INTERCEPTOR(int, sem_post, void *s) {
+INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
   COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
@@ -5167,7 +5172,7 @@ INTERCEPTOR(int, sem_post, void *s) {
   return res;
 }
 
-INTERCEPTOR(int, sem_getvalue, void *s, int *sval) {
+INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
   int res = REAL(sem_getvalue)(s, sval);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc?rev=250113&r1=250112&r2=250113&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc Mon Oct 12 16:32:30 2015
@@ -122,6 +122,7 @@
 # if defined(__mips64) || defined(__aarch64__)
 #  include <asm/ptrace.h>
 # endif
+# include <semaphore.h>
 #endif
 
 #if !SANITIZER_ANDROID
@@ -1241,4 +1242,8 @@ CHECK_SIZE_AND_OFFSET(cookie_io_function
 CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close);
 #endif
 
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+CHECK_TYPE_SIZE(sem_t);
+#endif
+
 #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=250113&r1=250112&r2=250113&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Mon Oct 12 16:32:30 2015
@@ -150,6 +150,18 @@ namespace __sanitizer {
   };
 
   const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+  struct __sanitizer_sem_t {
+#if SANITIZER_ANDROID && defined(_LP64)
+    int data[4];
+#elif SANITIZER_ANDROID && !defined(_LP64)
+    int data;
+#elif SANITIZER_LINUX
+    uptr data[4];
+#elif SANITIZER_FREEBSD
+    u32 data[4];
+#endif
+  };
 #endif // SANITIZER_LINUX || SANITIZER_FREEBSD
 
 #if SANITIZER_ANDROID

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc?rev=250113&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc Mon Oct 12 16:32:30 2015
@@ -0,0 +1,32 @@
+// RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t
+// This test depends on the glibc layout of struct sem_t and checks that we
+// don't leave sem_t::private uninitialized.
+// UNSUPPORTED: android
+#include <assert.h>
+#include <semaphore.h>
+#include <string.h>
+
+void my_sem_init(bool priv, int value, unsigned *a, unsigned char *b) {
+  sem_t sem;
+  memset(&sem, 0xAB, sizeof(sem));
+  sem_init(&sem, priv, value);
+
+  char *p = (char *)&sem;
+  memcpy(a, p, sizeof(unsigned));
+  memcpy(b, p + sizeof(unsigned), sizeof(char));
+
+  sem_destroy(&sem);
+}
+
+int main() {
+  unsigned a;
+  unsigned char b;
+
+  my_sem_init(false, 42, &a, &b);
+  assert(a == 42);
+  assert(b != 0xAB);
+
+  my_sem_init(true, 43, &a, &b);
+  assert(a == 43);
+  assert(b != 0xAB);
+}




More information about the llvm-commits mailing list