[klibc] [PATCH 2/2] ia64: Fix sigaction struct layout and function implementation
James Clarke
jrtc27 at jrtc27.com
Fri Feb 1 17:35:57 PST 2019
Commit 8418552 ("[klibc] ia64: Fix shared build") switched to the
function descriptor-less ABI. However, when passing a function pointer
to the kernel for signal handling, it always expects a descriptor, and
-mno-pic does not set any ELF flags that the kernel could detect. Thus
to fix this regression we must construct descriptors solely for passing
to/from the kernel.
Despite this, usr/dash/static/sh -c "usr/utils/static/true; exit" was
still seen to hang during the test suite. This is because sa_mask and
sa_flags were round the wrong way (matching the old sigaction syscall
rather than the newer rt_sigaction syscall, despite the former not
existing on ia64), causing the kernel to think SA_NOCLDWAIT was set.
This bug appears to have been present since the ia64 port was first
committed.
---
usr/include/arch/ia64/klibc/archsignal.h | 3 ++-
usr/klibc/sigaction.c | 45 +++++++++++++++++++++++++++++++-
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/usr/include/arch/ia64/klibc/archsignal.h b/usr/include/arch/ia64/klibc/archsignal.h
index fbc961b..c52c41a 100644
--- a/usr/include/arch/ia64/klibc/archsignal.h
+++ b/usr/include/arch/ia64/klibc/archsignal.h
@@ -22,8 +22,9 @@ struct sigaction {
__sighandler_t _sa_handler;
void (*_sa_sigaction) (int, struct siginfo *, void *);
} _u;
- sigset_t sa_mask;
int sa_flags;
+ int __pad0;
+ sigset_t sa_mask;
};
#define sa_handler _u._sa_handler
diff --git a/usr/klibc/sigaction.c b/usr/klibc/sigaction.c
index 19a8a54..e4901ab 100644
--- a/usr/klibc/sigaction.c
+++ b/usr/klibc/sigaction.c
@@ -19,13 +19,30 @@ __extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *,
size_t);
#endif
+#ifdef __ia64__
+/* We use -mno-pic so our function pointers are straight to the function entry
+ point, but the kernel always expects a descriptor. Thus we create a fake
+ descriptor for each possible signal, update it, and pass that to the kernel
+ instead (the descriptor must remain valid after returning from sigaction
+ until it is replaced). */
+struct {
+ uintptr_t entry;
+ uintptr_t gp;
+} signal_descriptors[_NSIG];
+#endif
+
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
int rv;
-#if _KLIBC_NEEDS_SA_RESTORER
+#if _KLIBC_NEEDS_SA_RESTORER || defined(__ia64__)
struct sigaction sa;
+#endif
+#ifdef __ia64__
+ uintptr_t old_entry;
+#endif
+#if _KLIBC_NEEDS_SA_RESTORER
if (act && !(act->sa_flags & SA_RESTORER)) {
sa = *act;
act = &sa;
@@ -37,6 +54,26 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
}
#endif
+#ifdef __ia64__
+ if (sig < 0 || sig >= _NSIG) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (oact) {
+ old_entry = signal_descriptors[sig].entry;
+ }
+
+ if (act && act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
+ sa = *act;
+ act = &sa;
+
+ signal_descriptors[sig].entry = (uintptr_t)sa.sa_handler;
+
+ sa.sa_handler = (__sighandler_t)(uintptr_t)&signal_descriptors[sig];
+ }
+#endif
+
#if _KLIBC_USE_RT_SIG
# ifdef __sparc__
{
@@ -61,5 +98,11 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
}
#endif
+#ifdef __ia64__
+ if (oact && oact->sa_handler != SIG_IGN && oact->sa_handler != SIG_DFL) {
+ oact->sa_handler = (__sighandler_t)old_entry;
+ }
+#endif
+
return rv;
}
--
1.8.5.3
More information about the klibc
mailing list