Merge "Allow invoking the linker on an executable."
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index 3df8b18..41b2657 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -71,7 +71,7 @@
sigset64_t mutable_ss;
sigset64_t* mutable_ss_ptr = nullptr;
if (ss != nullptr) {
- mutable_ss = filter_reserved_signals(*ss);
+ mutable_ss = filter_reserved_signals(*ss, SIG_SETMASK);
mutable_ss_ptr = &mutable_ss;
}
@@ -121,7 +121,7 @@
sigset64_t mutable_ss;
sigset64_t* mutable_ss_ptr = nullptr;
if (ss != nullptr) {
- mutable_ss = filter_reserved_signals(*ss);
+ mutable_ss = filter_reserved_signals(*ss, SIG_SETMASK);
mutable_ss_ptr = &mutable_ss;
}
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
index fb57d1c..42dcccd 100644
--- a/libc/bionic/sigaction.cpp
+++ b/libc/bionic/sigaction.cpp
@@ -43,7 +43,7 @@
if (bionic_new_action != nullptr) {
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 = filter_reserved_signals(bionic_new_action->sa_mask);
+ kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask, SIG_SETMASK);
#if defined(SA_RESTORER)
kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
#if defined(__aarch64__)
@@ -122,7 +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);
+ kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask, SIG_SETMASK);
}
return __rt_sigaction(signal,
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 175182b..d6be09a 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -263,7 +263,7 @@
sigset64_t mutable_set;
sigset64_t* mutable_set_ptr = nullptr;
if (set) {
- mutable_set = filter_reserved_signals(*set);
+ mutable_set = filter_reserved_signals(*set, SIG_SETMASK);
mutable_set_ptr = &mutable_set;
}
return __rt_sigsuspend(mutable_set_ptr, sizeof(*set));
@@ -279,7 +279,7 @@
sigset64_t mutable_set;
sigset64_t* mutable_set_ptr = nullptr;
if (set) {
- mutable_set = filter_reserved_signals(*set);
+ mutable_set = filter_reserved_signals(*set, SIG_SETMASK);
mutable_set_ptr = &mutable_set;
}
return __rt_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set));
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
index 36866f3..5f70f32 100644
--- a/libc/bionic/sigprocmask.cpp
+++ b/libc/bionic/sigprocmask.cpp
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+#include <errno.h>
#include <signal.h>
#include "private/sigrtmin.h"
@@ -65,10 +66,16 @@
int sigprocmask64(int how,
const sigset64_t* new_set,
sigset64_t* old_set) __attribute__((__noinline__)) {
+ // how is only checked for validity if new_set is provided.
+ if (new_set && how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) {
+ errno = EINVAL;
+ return -1;
+ }
+
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 = filter_reserved_signals(*new_set, how);
mutable_new_set_ptr = &mutable_new_set;
}
return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set));
diff --git a/libc/include/bits/sysconf.h b/libc/include/bits/sysconf.h
index 2cbbb11..8607adf 100644
--- a/libc/include/bits/sysconf.h
+++ b/libc/include/bits/sysconf.h
@@ -73,6 +73,7 @@
#define _SC_XOPEN_LEGACY 0x0024
#define _SC_ATEXIT_MAX 0x0025
#define _SC_IOV_MAX 0x0026
+#define _SC_UIO_MAXIOV _SC_IOV_MAX
#define _SC_PAGESIZE 0x0027
#define _SC_PAGE_SIZE 0x0028
#define _SC_XOPEN_UNIX 0x0029
diff --git a/libc/private/sigrtmin.h b/libc/private/sigrtmin.h
index ea8673d..431a1dd 100644
--- a/libc/private/sigrtmin.h
+++ b/libc/private/sigrtmin.h
@@ -32,6 +32,8 @@
#include <signal.h>
+#include "bionic_macros.h"
+
// Realtime signals reserved for internal use:
// 32 (__SIGRTMIN + 0) POSIX timers
// 33 (__SIGRTMIN + 1) libbacktrace
@@ -42,9 +44,29 @@
// in <android/legacy_signal_inlines.h> to match.
#define __SIGRT_RESERVED 4
-static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset) {
- for (int signo = __SIGRTMIN; signo < __SIGRTMIN + __SIGRT_RESERVED; ++signo) {
- sigdelset64(&sigset, signo);
+static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
+ int (*block)(sigset64_t*, int);
+ int (*unblock)(sigset64_t*, int);
+ switch (how) {
+ case SIG_BLOCK:
+ __BIONIC_FALLTHROUGH;
+ case SIG_SETMASK:
+ block = sigaddset64;
+ unblock = sigdelset64;
+ break;
+
+ case SIG_UNBLOCK:
+ block = sigdelset64;
+ unblock = sigaddset64;
+ break;
}
+
+ // The POSIX timer signal must be blocked.
+ block(&sigset, __SIGRTMIN + 0);
+
+ // Everything else must remain unblocked.
+ unblock(&sigset, __SIGRTMIN + 1);
+ unblock(&sigset, __SIGRTMIN + 2);
+ unblock(&sigset, __SIGRTMIN + 3);
return sigset;
}
diff --git a/tests/SignalUtils.h b/tests/SignalUtils.h
index ece28ba..a2faf0a 100644
--- a/tests/SignalUtils.h
+++ b/tests/SignalUtils.h
@@ -55,3 +55,12 @@
private:
sigset64_t old_mask_;
};
+
+// uint64_t equivalents of sigsetops.
+static inline void SignalSetAdd(uint64_t* sigset, int signo) {
+ *sigset |= 1ULL << (signo - 1);
+}
+
+static inline void SignalSetDel(uint64_t* sigset, int signo) {
+ *sigset &= ~(1ULL << (signo - 1));
+}
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 05339a6..dde0be1 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -74,6 +74,8 @@
sigset64_t ss;
sigemptyset64(&ss);
sigaddset64(&ss, SIGUSR1 + offset);
+ // TIMER_SIGNAL.
+ sigaddset64(&ss, __SIGRTMIN);
sigaddset64(&ss, SIGRTMIN + offset);
return ss;
}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 52a097b..dd27aef 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -22,6 +22,7 @@
#include <thread>
+#include <android-base/macros.h>
#include <gtest/gtest.h>
#include "SignalUtils.h"
@@ -339,6 +340,17 @@
static void ClearSignalMask() {
uint64_t sigset = 0;
+ SignalSetAdd(&sigset, __SIGRTMIN);
+ if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) {
+ abort();
+ }
+}
+
+static void FillSignalMask() {
+ uint64_t sigset = ~0ULL;
+ for (int signo = __SIGRTMIN + 1; signo < SIGRTMIN; ++signo) {
+ SignalSetDel(&sigset, signo);
+ }
if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) {
abort();
}
@@ -352,40 +364,27 @@
return sigset;
}
-enum class SignalMaskFunctionType {
- RtAware,
- RtNonaware,
-};
-
-#if defined(__LP64__) || !defined(__BIONIC__)
-constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtAware;
-#else
-constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtNonaware;
-#endif
-
-static void TestSignalMaskFiltered(uint64_t sigset, SignalMaskFunctionType type) {
- for (int signo = 1; signo <= 64; ++signo) {
+static void TestSignalMaskFiltered(uint64_t sigset) {
+#if defined(__BIONIC__)
+ for (int signo = __SIGRTMIN; signo < SIGRTMIN; ++signo) {
bool signal_blocked = sigset & (1ULL << (signo - 1));
- if (signo == SIGKILL || signo == SIGSTOP) {
- // SIGKILL and SIGSTOP shouldn't be blocked.
- EXPECT_EQ(false, signal_blocked) << "signal " << signo;
- } else if (signo < __SIGRTMIN) {
- // Everything else should be blocked.
+ if (signo == __SIGRTMIN) {
+ // TIMER_SIGNAL must be blocked.
EXPECT_EQ(true, signal_blocked) << "signal " << signo;
- } else if (signo >= __SIGRTMIN && signo < SIGRTMIN) {
- // Reserved signals must not be blocked.
+ } else {
+ // The other reserved signals must not be blocked.
EXPECT_EQ(false, signal_blocked) << "signal " << signo;
- } else if (type == SignalMaskFunctionType::RtAware) {
- // Realtime signals should be blocked, unless we blocked using a non-rt aware function.
- EXPECT_EQ(true, signal_blocked) << "signal " << signo;
}
}
+#else
+ UNUSED(sigset);
+#endif
}
-static void TestSignalMaskFunction(std::function<void()> fn, SignalMaskFunctionType fn_type) {
+static void TestSignalMaskFunction(std::function<void()> fn) {
ClearSignalMask();
fn();
- TestSignalMaskFiltered(GetSignalMask(), fn_type);
+ TestSignalMaskFiltered(GetSignalMask());
}
TEST(signal, sigaction_filter) {
@@ -397,7 +396,7 @@
sigaction(SIGUSR1, &sa, nullptr);
raise(SIGUSR1);
ASSERT_NE(0ULL, sigset);
- TestSignalMaskFiltered(sigset, sigset_type);
+ TestSignalMaskFiltered(sigset);
}
TEST(signal, sigaction64_filter) {
@@ -409,111 +408,135 @@
sigaction64(SIGUSR1, &sa, nullptr);
raise(SIGUSR1);
ASSERT_NE(0ULL, sigset);
- TestSignalMaskFiltered(sigset, SignalMaskFunctionType::RtAware);
+ TestSignalMaskFiltered(sigset);
}
TEST(signal, sigprocmask_setmask_filter) {
- TestSignalMaskFunction(
- []() {
- sigset_t sigset_libc;
- sigfillset(&sigset_libc);
- ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr));
- },
- sigset_type);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr));
+ });
}
TEST(signal, sigprocmask64_setmask_filter) {
- TestSignalMaskFunction(
- []() {
- sigset64_t sigset_libc;
- sigfillset64(&sigset_libc);
- ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr));
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr));
+ });
}
TEST(signal, pthread_sigmask_setmask_filter) {
- TestSignalMaskFunction(
- []() {
- sigset_t sigset_libc;
- sigfillset(&sigset_libc);
- ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr));
- },
- sigset_type);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr));
+ });
}
TEST(signal, pthread_sigmask64_setmask_filter) {
- TestSignalMaskFunction(
- []() {
- sigset64_t sigset_libc;
- sigfillset64(&sigset_libc);
- ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr));
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr));
+ });
}
TEST(signal, sigprocmask_block_filter) {
- TestSignalMaskFunction(
- []() {
- sigset_t sigset_libc;
- sigfillset(&sigset_libc);
- ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr));
- },
- sigset_type);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr));
+ });
}
TEST(signal, sigprocmask64_block_filter) {
- TestSignalMaskFunction(
- []() {
- sigset64_t sigset_libc;
- sigfillset64(&sigset_libc);
- ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr));
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr));
+ });
}
TEST(signal, pthread_sigmask_block_filter) {
- TestSignalMaskFunction(
- []() {
- sigset_t sigset_libc;
- sigfillset(&sigset_libc);
- ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr));
- },
- sigset_type);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr));
+ });
}
TEST(signal, pthread_sigmask64_block_filter) {
- TestSignalMaskFunction(
- []() {
- sigset64_t sigset_libc;
- sigfillset64(&sigset_libc);
- ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr));
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ ClearSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr));
+ });
+}
+
+TEST(signal, sigprocmask_unblock_filter) {
+ TestSignalMaskFunction([]() {
+ FillSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &sigset_libc, nullptr));
+ });
+}
+
+TEST(signal, sigprocmask64_unblock_filter) {
+ TestSignalMaskFunction([]() {
+ FillSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, sigprocmask64(SIG_UNBLOCK, &sigset_libc, nullptr));
+ });
+}
+
+TEST(signal, pthread_sigmask_unblock_filter) {
+ TestSignalMaskFunction([]() {
+ FillSignalMask();
+ sigset_t sigset_libc;
+ sigfillset(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigset_libc, nullptr));
+ });
+}
+
+TEST(signal, pthread_sigmask64_unblock_filter) {
+ TestSignalMaskFunction([]() {
+ FillSignalMask();
+ sigset64_t sigset_libc;
+ sigfillset64(&sigset_libc);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_UNBLOCK, &sigset_libc, nullptr));
+ });
}
// glibc filters out signals via sigfillset, not the actual underlying functions.
TEST(signal, sigset_filter) {
#if defined(__BIONIC__)
- TestSignalMaskFunction(
- []() {
- for (int i = 1; i <= 64; ++i) {
- sigset(i, SIG_HOLD);
- }
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ for (int i = 1; i <= 64; ++i) {
+ sigset(i, SIG_HOLD);
+ }
+ });
#endif
}
TEST(signal, sighold_filter) {
#if defined(__BIONIC__)
- TestSignalMaskFunction(
- []() {
- for (int i = 1; i <= 64; ++i) {
- sighold(i);
- }
- },
- SignalMaskFunctionType::RtAware);
+ TestSignalMaskFunction([]() {
+ for (int i = 1; i <= 64; ++i) {
+ sighold(i);
+ }
+ });
#endif
}
@@ -525,23 +548,17 @@
TEST(signal, sigblock_filter) {
#if defined(__BIONIC__)
- TestSignalMaskFunction(
- []() {
- int mask = ~0U;
- ASSERT_EQ(0, sigblock(mask));
- },
- SignalMaskFunctionType::RtNonaware);
+ TestSignalMaskFunction([]() {
+ sigblock(~0U);
+ });
#endif
}
TEST(signal, sigsetmask_filter) {
#if defined(__BIONIC__)
- TestSignalMaskFunction(
- []() {
- int mask = ~0U;
- ASSERT_EQ(0, sigsetmask(mask));
- },
- SignalMaskFunctionType::RtNonaware);
+ TestSignalMaskFunction([]() {
+ sigsetmask(~0U);
+ });
#endif
}
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index a5e7e56..04b66d3 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -396,7 +396,13 @@
// Check that's what happens...
ProcStatus ps = {};
GetChildStatus(&sa, &ps);
- EXPECT_EQ(static_cast<uint64_t>(1 << (SIGALRM - 1)), ps.sigblk);
+
+ // TIMER_SIGNAL should also be blocked.
+ uint64_t expected_blocked = 0;
+ SignalSetAdd(&expected_blocked, SIGALRM);
+ SignalSetAdd(&expected_blocked, __SIGRTMIN + 0);
+ EXPECT_EQ(expected_blocked, ps.sigblk);
+
EXPECT_EQ(static_cast<uint64_t>(0), ps.sigign);
ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
@@ -421,8 +427,15 @@
// Check that's what happens...
ProcStatus ps = {};
GetChildStatus(&sa, &ps);
- EXPECT_EQ(static_cast<uint64_t>(0), ps.sigblk);
- EXPECT_EQ(static_cast<uint64_t>(1 << (SIGCONT - 1)), ps.sigign);
+
+ // TIMER_SIGNAL should be blocked.
+ uint64_t expected_blocked = 0;
+ SignalSetAdd(&expected_blocked, __SIGRTMIN + 0);
+ EXPECT_EQ(expected_blocked, ps.sigblk);
+
+ uint64_t expected_ignored = 0;
+ SignalSetAdd(&expected_ignored, SIGCONT);
+ EXPECT_EQ(expected_ignored, ps.sigign);
ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 1f7f555..da083de 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -886,6 +886,8 @@
VerifySysconf(_SC_XOPEN_VERSION, "_SC_XOPEN_VERSION", [](long v){return v == _XOPEN_VERSION && errno == 0;});
VERIFY_SYSCONF_POSITIVE(_SC_ATEXIT_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_IOV_MAX);
+ VERIFY_SYSCONF_POSITIVE(_SC_UIO_MAXIOV);
+ EXPECT_EQ(sysconf(_SC_IOV_MAX), sysconf(_SC_UIO_MAXIOV));
VERIFY_SYSCONF_POSITIVE(_SC_PAGESIZE);
VERIFY_SYSCONF_POSITIVE(_SC_PAGE_SIZE);
VerifySysconf(_SC_PAGE_SIZE, "_SC_PAGE_SIZE",