[compiler-rt] [sanitizer_common] AND signals in BlockSignals instead of deleting (PR #113443)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 23 04:09:10 PDT 2024
https://github.com/thurstond created https://github.com/llvm/llvm-project/pull/113443
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
>From 0672505f025c23c22f1aea75c69b557216d2c9a2 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 23 Oct 2024 11:04:27 +0000
Subject: [PATCH] [sanitizer_common] AND signals in BlockSignals instead of
deleting
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
---
.../lib/sanitizer_common/sanitizer_linux.cpp | 36 ++++++++++++-------
1 file changed, 24 insertions(+), 12 deletions(-)
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, ¤tset);
+
+ __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, ¤tset, SIGSEGV);
+ internal_sigandset_individual(&newset, ¤tset, SIGBUS);
+ internal_sigandset_individual(&newset, ¤tset, SIGILL);
+ internal_sigandset_individual(&newset, ¤tset, SIGTRAP);
+ internal_sigandset_individual(&newset, ¤tset, SIGABRT);
+ internal_sigandset_individual(&newset, ¤tset, SIGFPE);
+ internal_sigandset_individual(&newset, ¤tset, SIGPIPE);
# endif
- SetSigProcMask(&set, oldset);
+ SetSigProcMask(&newset, oldset);
}
ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {
More information about the llvm-commits
mailing list