Filter out reserved signals in functions that take sigset_t.
Prevent processes from blocking libc-reserved signals by filtering them
out.
Bug: http://b/73144101
Test: 32/64-bit bionic-unit-tests-glibc
Test: 32/64-bit bionic-unit-tests on taimen
Change-Id: Ibadcaa7f668ed8be885cc61b67fb4b611fce8b17
diff --git a/libc/bionic/__libc_current_sigrtmin.cpp b/libc/bionic/__libc_current_sigrtmin.cpp
index 04caa89..d2ea75d 100644
--- a/libc/bionic/__libc_current_sigrtmin.cpp
+++ b/libc/bionic/__libc_current_sigrtmin.cpp
@@ -28,14 +28,8 @@
#include <signal.h>
-// Realtime signals reserved for internal use:
-// 32 (__SIGRTMIN + 0) POSIX timers
-// 33 (__SIGRTMIN + 1) libbacktrace
-// 34 (__SIGRTMIN + 2) libcore
-// 35 (__SIGRTMIN + 3) debuggerd -b
+#include "private/sigrtmin.h"
-int __libc_current_sigrtmin(void) {
- // If you change this, also change __ndk_legacy___libc_current_sigrtmin
- // in <android/legacy_signal_inlines.h> to match.
- return __SIGRTMIN + 4;
+int __libc_current_sigrtmin() {
+ return __SIGRTMIN + __SIGRT_RESERVED;
}
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index 1a54832..3df8b18 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -31,6 +31,7 @@
#include <sys/select.h>
#include "private/bionic_time_conversions.h"
+#include "private/sigrtmin.h"
#include "private/SigSetConverter.h"
extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t);
@@ -66,7 +67,15 @@
mutable_ts = *ts;
mutable_ts_ptr = &mutable_ts;
}
- return __ppoll(fds, fd_count, mutable_ts_ptr, ss, sizeof(*ss));
+
+ sigset64_t mutable_ss;
+ sigset64_t* mutable_ss_ptr = nullptr;
+ if (ss != nullptr) {
+ mutable_ss = filter_reserved_signals(*ss);
+ mutable_ss_ptr = &mutable_ss;
+ }
+
+ return __ppoll(fds, fd_count, mutable_ts_ptr, mutable_ss_ptr, sizeof(*mutable_ss_ptr));
}
int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, timeval* tv) {
@@ -109,6 +118,13 @@
mutable_ts_ptr = &mutable_ts;
}
+ sigset64_t mutable_ss;
+ sigset64_t* mutable_ss_ptr = nullptr;
+ if (ss != nullptr) {
+ mutable_ss = filter_reserved_signals(*ss);
+ mutable_ss_ptr = &mutable_ss;
+ }
+
// The Linux kernel only handles 6 arguments and this system call really needs 7,
// so the last argument is a void* pointing to:
struct pselect6_extra_data_t {
@@ -116,8 +132,8 @@
size_t ss_len;
};
pselect6_extra_data_t extra_data;
- extra_data.ss_addr = reinterpret_cast<uintptr_t>(ss);
- extra_data.ss_len = sizeof(*ss);
+ extra_data.ss_addr = reinterpret_cast<uintptr_t>(mutable_ss_ptr);
+ extra_data.ss_len = sizeof(*mutable_ss_ptr);
return __pselect6(fd_count, read_fds, write_fds, error_fds, mutable_ts_ptr, &extra_data);
}
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index 2edfe97..1abeb1f 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -35,6 +35,8 @@
#include <time.h>
// System calls.
+extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
+extern "C" int __rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t);
extern "C" int __timer_create(clockid_t, sigevent*, __kernel_timer_t*);
extern "C" int __timer_delete(__kernel_timer_t);
extern "C" int __timer_getoverrun(__kernel_timer_t);
@@ -77,7 +79,7 @@
while (true) {
// Wait for a signal...
siginfo_t si = {};
- if (sigtimedwait64(&sigset, &si, nullptr) == -1) continue;
+ if (__rt_sigtimedwait(&sigset, &si, nullptr, sizeof(sigset)) == -1) continue;
if (si.si_code == SI_TIMER) {
// This signal was sent because a timer fired, so call the callback.
@@ -146,11 +148,13 @@
sigset64_t sigset = {};
sigaddset64(&sigset, TIMER_SIGNAL);
sigset64_t old_sigset;
- sigprocmask64(SIG_BLOCK, &sigset, &old_sigset);
+
+ // Use __rt_sigprocmask instead of sigprocmask64 to avoid filtering out TIMER_SIGNAL.
+ __rt_sigprocmask(SIG_BLOCK, &sigset, &old_sigset, sizeof(sigset));
int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer);
- sigprocmask64(SIG_SETMASK, &old_sigset, nullptr);
+ __rt_sigprocmask(SIG_BLOCK, &old_sigset, nullptr, sizeof(old_sigset));
if (rc != 0) {
free(timer);
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
index 19a08e6..41923cf 100644
--- a/libc/bionic/sigaction.cpp
+++ b/libc/bionic/sigaction.cpp
@@ -29,6 +29,8 @@
#include <signal.h>
#include <string.h>
+#include "private/sigrtmin.h"
+
extern "C" void __restore_rt(void);
extern "C" void __restore(void);
@@ -41,7 +43,7 @@
if (bionic_new_action != NULL) {
kernel_new_action.sa_flags = bionic_new_action->sa_flags;
kernel_new_action.sa_handler = bionic_new_action->sa_handler;
- kernel_new_action.sa_mask = bionic_new_action->sa_mask;
+ kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask);
#if defined(SA_RESTORER)
kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
#if defined(__aarch64__)
@@ -120,6 +122,7 @@
kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
}
#endif
+ kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask);
}
return __rt_sigaction(signal,
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index f2e19c2..175182b 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -38,6 +38,7 @@
#include "private/ErrnoRestorer.h"
#include "private/SigSetConverter.h"
+#include "private/sigrtmin.h"
extern "C" int __rt_sigpending(const sigset64_t*, size_t);
extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
@@ -255,21 +256,33 @@
int sigsuspend(const sigset_t* bionic_set) {
SigSetConverter set = {};
set.sigset = *bionic_set;
- return __rt_sigsuspend(&set.sigset64, sizeof(set.sigset64));
+ return sigsuspend64(&set.sigset64);
}
int sigsuspend64(const sigset64_t* set) {
- return __rt_sigsuspend(set, sizeof(*set));
+ sigset64_t mutable_set;
+ sigset64_t* mutable_set_ptr = nullptr;
+ if (set) {
+ mutable_set = filter_reserved_signals(*set);
+ mutable_set_ptr = &mutable_set;
+ }
+ return __rt_sigsuspend(mutable_set_ptr, sizeof(*set));
}
int sigtimedwait(const sigset_t* bionic_set, siginfo_t* info, const timespec* timeout) {
SigSetConverter set = {};
set.sigset = *bionic_set;
- return __rt_sigtimedwait(&set.sigset64, info, timeout, sizeof(set.sigset64));
+ return sigtimedwait64(&set.sigset64, info, timeout);
}
int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) {
- return __rt_sigtimedwait(set, info, timeout, sizeof(*set));
+ sigset64_t mutable_set;
+ sigset64_t* mutable_set_ptr = nullptr;
+ if (set) {
+ mutable_set = filter_reserved_signals(*set);
+ mutable_set_ptr = &mutable_set;
+ }
+ return __rt_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set));
}
int sigwait(const sigset_t* bionic_set, int* sig) {
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
index 00b5df4..36866f3 100644
--- a/libc/bionic/sigprocmask.cpp
+++ b/libc/bionic/sigprocmask.cpp
@@ -28,6 +28,7 @@
#include <signal.h>
+#include "private/sigrtmin.h"
#include "private/SigSetConverter.h"
extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
@@ -64,5 +65,11 @@
int sigprocmask64(int how,
const sigset64_t* new_set,
sigset64_t* old_set) __attribute__((__noinline__)) {
- return __rt_sigprocmask(how, new_set, old_set, sizeof(*new_set));
+ sigset64_t mutable_new_set;
+ sigset64_t* mutable_new_set_ptr = nullptr;
+ if (new_set) {
+ mutable_new_set = filter_reserved_signals(*new_set);
+ mutable_new_set_ptr = &mutable_new_set;
+ }
+ return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set));
}