[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