Add `struct sigaction64` and `sigaction64`.
Bug: http://b/72493232
Test: ran tests
Change-Id: I47b0560a30aa33a9b1f1978dfb7f84d2e3d389b8
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index ec26a50..d2c99a5 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -67,13 +67,10 @@
sigprocmask64(SIG_SETMASK, &mask, nullptr);
inline_tgkill(pid, tid, SIGABRT);
- // If SIGABRT ignored, or caught and the handler returns,
+ // If SIGABRT is ignored or it's caught and the handler returns,
// remove the SIGABRT signal handler and raise SIGABRT again.
- struct sigaction sa;
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_RESTART;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGABRT, &sa, &sa);
+ struct sigaction64 sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART };
+ sigaction64(SIGABRT, &sa, nullptr);
sigprocmask64(SIG_SETMASK, &mask, nullptr);
inline_tgkill(pid, tid, SIGABRT);
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
index 0633748..e5a7d5f 100644
--- a/libc/bionic/sigaction.cpp
+++ b/libc/bionic/sigaction.cpp
@@ -27,6 +27,7 @@
*/
#include <signal.h>
+#include <string.h>
extern "C" void __restore_rt(void);
extern "C" void __restore(void);
@@ -75,28 +76,49 @@
return result;
}
+__strong_alias(sigaction64, sigaction);
+
#else
+extern "C" int __rt_sigaction(int, const struct sigaction64*, struct sigaction64*, size_t);
extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*);
-int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) {
+int sigaction(int signal, const struct sigaction* bionic_new, struct sigaction* bionic_old) {
// The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t,
- // so we have to use sigaction(2) rather than rt_sigaction(2).
- struct sigaction kernel_new_action;
- 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;
-#if defined(SA_RESTORER)
- kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
-
- if (!(kernel_new_action.sa_flags & SA_RESTORER)) {
- kernel_new_action.sa_flags |= SA_RESTORER;
- kernel_new_action.sa_restorer = (kernel_new_action.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
- }
-#endif
+ // so we have to translate to struct sigaction64 first.
+ struct sigaction64 kernel_new;
+ if (bionic_new) {
+ kernel_new = {};
+ kernel_new.sa_flags = bionic_new->sa_flags;
+ kernel_new.sa_handler = bionic_new->sa_handler;
+ memcpy(&kernel_new.sa_mask, &bionic_new->sa_mask, sizeof(bionic_new->sa_mask));
}
- return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action);
+
+ struct sigaction64 kernel_old;
+ int result = sigaction64(signal, bionic_new ? &kernel_new : nullptr, &kernel_old);
+ if (bionic_old) {
+ *bionic_old = {};
+ bionic_old->sa_flags = kernel_old.sa_flags;
+ bionic_old->sa_handler = kernel_old.sa_handler;
+ memcpy(&bionic_old->sa_mask, &kernel_old.sa_mask, sizeof(bionic_old->sa_mask));
+ }
+ return result;
+}
+
+int sigaction64(int signal, const struct sigaction64* bionic_new, struct sigaction64* bionic_old) {
+ struct sigaction64 kernel_new;
+ if (bionic_new) {
+ kernel_new = *bionic_new;
+ if (!(kernel_new.sa_flags & SA_RESTORER)) {
+ kernel_new.sa_flags |= SA_RESTORER;
+ kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
+ }
+ }
+
+ return __rt_sigaction(signal,
+ bionic_new ? &kernel_new : nullptr,
+ bionic_old,
+ sizeof(kernel_new.sa_mask));
}
#endif
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 099944a..fbfe0ce 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -147,22 +147,19 @@
}
int sigignore(int sig) {
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- if (sigemptyset(&sa.sa_mask) == -1) return -1;
- sa.sa_handler = SIG_IGN;
- return sigaction(sig, &sa, nullptr);
+ struct sigaction64 sa = { .sa_handler = SIG_IGN };
+ return sigaction64(sig, &sa, nullptr);
}
int siginterrupt(int sig, int flag) {
- struct sigaction act;
- sigaction(sig, nullptr, &act);
+ struct sigaction64 act;
+ sigaction64(sig, nullptr, &act);
if (flag) {
act.sa_flags &= ~SA_RESTART;
} else {
act.sa_flags |= SA_RESTART;
}
- return sigaction(sig, &act, nullptr);
+ return sigaction64(sig, &act, nullptr);
}
template <typename SigSetT>
@@ -185,16 +182,8 @@
}
__LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) {
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = handler;
- sa.sa_flags = flags;
-
- if (sigaction(sig, &sa, &sa) == -1) {
- return SIG_ERR;
- }
-
- return sa.sa_handler;
+ struct sigaction64 sa = { .sa_handler = handler, .sa_flags = flags };
+ return (sigaction64(sig, &sa, &sa) == -1) ? SIG_ERR : sa.sa_handler;
}
sighandler_t signal(int sig, sighandler_t handler) {
@@ -262,15 +251,11 @@
}
sighandler_t sigset(int sig, sighandler_t disp) {
- struct sigaction new_sa;
- if (disp != SIG_HOLD) {
- memset(&new_sa, 0, sizeof(new_sa));
- new_sa.sa_handler = disp;
- sigemptyset(&new_sa.sa_mask);
- }
+ struct sigaction64 new_sa;
+ if (disp != SIG_HOLD) new_sa = { .sa_handler = disp };
- struct sigaction old_sa;
- if (sigaction(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
+ struct sigaction64 old_sa;
+ if (sigaction64(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
return SIG_ERR;
}
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 7422a0b..fde102c 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -98,17 +98,17 @@
// POSIX: "Signals set to be caught by the calling process shall be
// set to the default action in the child process."
bool use_sigdefault = ((flags & POSIX_SPAWN_SETSIGDEF) != 0);
- const struct sigaction default_sa = { .sa_handler = SIG_DFL };
+ const struct sigaction64 default_sa = { .sa_handler = SIG_DFL };
for (int s = 1; s < _NSIG; ++s) {
bool reset = false;
if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) {
reset = true;
} else {
- struct sigaction current;
- if (sigaction(s, nullptr, ¤t) == -1) _exit(127);
+ struct sigaction64 current;
+ if (sigaction64(s, nullptr, ¤t) == -1) _exit(127);
reset = (current.sa_handler != SIG_IGN && current.sa_handler != SIG_DFL);
}
- if (reset && sigaction(s, &default_sa, nullptr) == -1) _exit(127);
+ if (reset && sigaction64(s, &default_sa, nullptr) == -1) _exit(127);
}
if ((flags & POSIX_SPAWN_SETPGROUP) != 0 && setpgid(0, (*attr)->pgroup) == -1) _exit(127);
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 61bb395..2027d70 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -40,7 +40,8 @@
/* For 64-bit (and mips), the kernel's struct sigaction doesn't match the
* POSIX one, so we need to expose our own and translate behind the scenes.
* For 32-bit, we're stuck with the definitions we already shipped,
- * even though they contain a sigset_t that's too small. */
+ * even though they contain a sigset_t that's too small. See sigaction64.
+ */
#define sigaction __kernel_sigaction
#include <linux/signal.h>
#undef sigaction
@@ -89,43 +90,65 @@
#if defined(__LP64__)
+#define __SIGACTION_BODY \
+ int sa_flags; \
+ union { \
+ sighandler_t sa_handler; \
+ void (*sa_sigaction)(int, struct siginfo*, void*); \
+ }; \
+ sigset_t sa_mask; \
+ void (*sa_restorer)(void); \
+
+struct sigaction { __SIGACTION_BODY };
+struct sigaction64 { __SIGACTION_BODY };
+
+#undef __SIGACTION_BODY
+
+#elif defined(__mips__)
+
+#define __SIGACTION_BODY \
+ int sa_flags; \
+ union { \
+ sighandler_t sa_handler; \
+ void (*sa_sigaction)(int, struct siginfo*, void*); \
+ }; \
+ sigset_t sa_mask; \
+
+struct sigaction { __SIGACTION_BODY };
+struct sigaction64 { __SIGACTION_BODY };
+
+#undef __SIGACTION_BODY
+
+#else
+
+#undef sa_handler
+#undef sa_sigaction
+
struct sigaction {
- int sa_flags;
union {
sighandler_t sa_handler;
void (*sa_sigaction)(int, struct siginfo*, void*);
};
sigset_t sa_mask;
+ int sa_flags;
void (*sa_restorer)(void);
};
-#elif defined(__mips__)
-
-struct sigaction {
- int sa_flags;
+/* This matches the kernel's internal structure. */
+struct sigaction64 {
union {
sighandler_t sa_handler;
- void (*sa_sigaction) (int, struct siginfo*, void*);
+ void (*sa_sigaction)(int, struct siginfo*, void*);
};
- sigset_t sa_mask;
-};
-
-#else
-
-struct sigaction {
- union {
- sighandler_t _sa_handler;
- void (*_sa_sigaction)(int, struct siginfo*, void*);
- } _u;
- sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
+ sigset64_t sa_mask;
};
#endif
-// TODO: sigaction contains a sigset_t that's too small on LP32.
int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action);
+int sigaction64(int __signal, const struct sigaction64* __new_action, struct sigaction64* __old_action) __INTRODUCED_IN(28);
int siginterrupt(int __signal, int __flag);
@@ -191,4 +214,4 @@
#include <android/legacy_signal_inlines.h>
-#endif /* _SIGNAL_H_ */
+#endif
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index c345ba6..839c406 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1386,6 +1386,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 3af0d42..a39a233 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1306,6 +1306,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 5c54ba1..b3bfa8a 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1411,6 +1411,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index c364608..2a93132 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1370,6 +1370,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 3af0d42..a39a233 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1306,6 +1306,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index eec2c19..d2e7399 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1368,6 +1368,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 3af0d42..a39a233 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1306,6 +1306,7 @@
sethostent;
setnetent;
setprotoent;
+ sigaction64;
sigaddset64;
sigdelset64;
sigemptyset64;
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index d597280..57d8f2a 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -59,13 +59,10 @@
bool BacktraceData::Initialize(const Config& config) {
enabled_ = config.backtrace_enabled();
if (config.backtrace_enable_on_signal()) {
- struct sigaction enable_act;
- memset(&enable_act, 0, sizeof(enable_act));
-
+ struct sigaction64 enable_act = {};
enable_act.sa_sigaction = ToggleBacktraceEnable;
enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&enable_act.sa_mask);
- if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) {
+ if (sigaction64(config.backtrace_signal(), &enable_act, nullptr) != 0) {
error_log("Unable to set up backtrace signal enable function: %s", strerror(errno));
return false;
}
@@ -73,13 +70,10 @@
config.backtrace_signal(), getpid());
}
- struct sigaction act;
- memset(&act, 0, sizeof(act));
-
+ struct sigaction64 act = {};
act.sa_sigaction = EnableDump;
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&act.sa_mask);
- if (sigaction(config.backtrace_dump_signal(), &act, nullptr) != 0) {
+ if (sigaction64(config.backtrace_dump_signal(), &act, nullptr) != 0) {
error_log("Unable to set up backtrace dump signal function: %s", strerror(errno));
return false;
}
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 5a68deb..55d9943 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -179,13 +179,10 @@
}
bool RecordData::Initialize(const Config& config) {
- struct sigaction dump_act;
- memset(&dump_act, 0, sizeof(dump_act));
-
+ struct sigaction64 dump_act = {};
dump_act.sa_sigaction = RecordDump;
dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&dump_act.sa_mask);
- if (sigaction(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
+ if (sigaction64(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
error_log("Unable to set up record dump signal function: %s", strerror(errno));
return false;
}