[compiler-rt] [sanitizer_common] AND signals in BlockSignals instead of deleting (PR #113443)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 23 04:09:44 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Thurston Dang (thurstond)

<details>
<summary>Changes</summary>

My earlier patch https://github.com/llvm/llvm-project/pull/98200 caused a regression because it unconditionally unblocked synchronous signals, even if the user program had deliberately blocked them. This patch fixes the issue by checking the current signal mask, as suggested by Vitaly.

Fixes #<!-- -->113385

---
Full diff: https://github.com/llvm/llvm-project/pull/113443.diff


1 Files Affected:

- (modified) compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp (+24-12) 


``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 33107eb0b42993..1f74abfb39b31e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -164,33 +164,45 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {
   CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));
 }
 
+// Deletes the specified signal from newset, if it is not present in oldset
+// Equivalently: newset[signum] = newset[signum] & oldset[signum]
+void internal_sigandset_individual(__sanitizer_sigset_t *newset,
+                                   __sanitizer_sigset_t *oldset, int signum) {
+  if (!internal_sigismember(oldset, signum))
+    internal_sigdelset(newset, signum);
+}
+
 // Block asynchronous signals
 void BlockSignals(__sanitizer_sigset_t *oldset) {
-  __sanitizer_sigset_t set;
-  internal_sigfillset(&set);
+  __sanitizer_sigset_t currentset;
+  SetSigProcMask(NULL, &currentset);
+
+  __sanitizer_sigset_t newset;
+  internal_sigfillset(&newset);
 #  if SANITIZER_LINUX && !SANITIZER_ANDROID
   // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
   // on any thread, setuid call hangs.
   // See test/sanitizer_common/TestCases/Linux/setuid.c.
-  internal_sigdelset(&set, 33);
+  internal_sigdelset(&newset, 33);
 #  endif
 #  if SANITIZER_LINUX
   // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.
   // If this signal is blocked, such calls cannot be handled and the process may
   // hang.
-  internal_sigdelset(&set, 31);
+  internal_sigdelset(&newset, 31);
 
   // Don't block synchronous signals
-  internal_sigdelset(&set, SIGSEGV);
-  internal_sigdelset(&set, SIGBUS);
-  internal_sigdelset(&set, SIGILL);
-  internal_sigdelset(&set, SIGTRAP);
-  internal_sigdelset(&set, SIGABRT);
-  internal_sigdelset(&set, SIGFPE);
-  internal_sigdelset(&set, SIGPIPE);
+  // but also don't unblock signals that the user had deliberately blocked.
+  internal_sigandset_individual(&newset, &currentset, SIGSEGV);
+  internal_sigandset_individual(&newset, &currentset, SIGBUS);
+  internal_sigandset_individual(&newset, &currentset, SIGILL);
+  internal_sigandset_individual(&newset, &currentset, SIGTRAP);
+  internal_sigandset_individual(&newset, &currentset, SIGABRT);
+  internal_sigandset_individual(&newset, &currentset, SIGFPE);
+  internal_sigandset_individual(&newset, &currentset, SIGPIPE);
 #  endif
 
-  SetSigProcMask(&set, oldset);
+  SetSigProcMask(&newset, oldset);
 }
 
 ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/113443


More information about the llvm-commits mailing list