[compiler-rt] 1a3b330 - [HWASan] Catch cases where libc populated jmp_buf.

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 15 07:55:08 PDT 2021


Author: Matt Morehouse
Date: 2021-09-15T07:53:54-07:00
New Revision: 1a3b3301d7aa9ab25a8bdf045c77298b087e3930

URL: https://github.com/llvm/llvm-project/commit/1a3b3301d7aa9ab25a8bdf045c77298b087e3930
DIFF: https://github.com/llvm/llvm-project/commit/1a3b3301d7aa9ab25a8bdf045c77298b087e3930.diff

LOG: [HWASan] Catch cases where libc populated jmp_buf.

Some setjmp calls within libc cannot be intercepted while their matching
longjmp calls can be.  This causes problems if our setjmp/longjmp
interceptors don't use the exact same format as libc for populating and
reading the jmp_buf.

We add a magic field to our jmp_buf and populate it in setjmp.  This
allows our longjmp interceptor to notice when a libc jmp_buf is passed
to it.

See discussion on https://reviews.llvm.org/D109699 and
https://reviews.llvm.org/D69045.

Fixes https://github.com/google/sanitizers/issues/1244.

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D109787

Added: 
    

Modified: 
    compiler-rt/lib/hwasan/hwasan.h
    compiler-rt/lib/hwasan/hwasan_interceptors.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h
index 1ea310a7051f0..f7978f2fa6811 100644
--- a/compiler-rt/lib/hwasan/hwasan.h
+++ b/compiler-rt/lib/hwasan/hwasan.h
@@ -199,12 +199,17 @@ struct __hw_jmp_buf_struct {
   // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
   // `__mask_was_saved' follows it.  Do not move these members or add others
   // before it.
+  //
+  // We add a __magic field to our struct to catch cases where libc's setjmp
+  // populated the jmp_buf instead of our interceptor.
   __hw_register_buf __jmpbuf; // Calling environment.
-  int __mask_was_saved;       // Saved the signal mask?
+  unsigned __mask_was_saved : 1;  // Saved the signal mask?
+  unsigned __magic : 31;      // Used to distinguish __hw_jmp_buf from jmp_buf.
   __hw_sigset_t __saved_mask; // Saved signal mask.
 };
 typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
 typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
+constexpr unsigned kHwJmpBufMagic = 0x248ACE77;
 #endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
 
 #define ENSURE_HWASAN_INITED()      \

diff  --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
index 3a1dbf288a595..5f8b49c3af81e 100644
--- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
@@ -58,6 +58,7 @@ extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
 #define SIG_BLOCK 0
 #define SIG_SETMASK 2
 extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
+  env[0].__magic = kHwJmpBufMagic;
   env[0].__mask_was_saved =
       (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
                                &env[0].__saved_mask) == 0);
@@ -103,6 +104,13 @@ InternalLongjmp(__hw_register_buf env, int retval) {
 }
 
 INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
+  if (env[0].__magic != kHwJmpBufMagic) {
+    Printf(
+        "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+        "there is a bug in HWASan.");
+    return REAL(siglongjmp)(env, val);
+  }
+
   if (env[0].__mask_was_saved)
     // Restore the saved signal mask.
     (void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
@@ -114,10 +122,18 @@ INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
 // _setjmp on start_thread.  Hence we have to intercept the longjmp on
 // pthread_exit so the __hw_jmp_buf order matches.
 INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
+  if (env[0].__magic != kHwJmpBufMagic)
+    return REAL(__libc_longjmp)(env, val);
   InternalLongjmp(env[0].__jmpbuf, val);
 }
 
 INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
+  if (env[0].__magic != kHwJmpBufMagic) {
+    Printf(
+        "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+        "there is a bug in HWASan.");
+    return REAL(longjmp)(env, val);
+  }
   InternalLongjmp(env[0].__jmpbuf, val);
 }
 #undef SIG_BLOCK
@@ -142,6 +158,11 @@ void InitializeInterceptors() {
 
 #if HWASAN_WITH_INTERCEPTORS
 #if defined(__linux__)
+#      if defined(__aarch64__)
+  INTERCEPT_FUNCTION(__libc_longjmp);
+  INTERCEPT_FUNCTION(longjmp);
+  INTERCEPT_FUNCTION(siglongjmp);
+#      endif  // __aarch64__
   INTERCEPT_FUNCTION(vfork);
 #endif  // __linux__
   INTERCEPT_FUNCTION(pthread_create);


        


More information about the llvm-commits mailing list