[klibc] [klibc:ia64-signal-fix] ia64: Fix sigaction struct layout and function implementation

klibc-bot for Jessica Clarke jrtc27 at jrtc27.com
Fri Aug 28 12:36:06 PDT 2020


Commit-ID:  454901a0c733986bee36da111a08fe7df0ff0b98
Gitweb:     http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=454901a0c733986bee36da111a08fe7df0ff0b98
Author:     Jessica Clarke <jrtc27 at jrtc27.com>
AuthorDate: Fri, 28 Aug 2020 19:48:32 +0100
Committer:  Ben Hutchings <ben at decadent.org.uk>
CommitDate: Fri, 28 Aug 2020 20:22:50 +0100

[klibc] ia64: Fix sigaction struct layout and function implementation

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.

[bwh: Moved the fix-up into an arch-specific source file and
 defined _KLIBC_NEEDS_SIGACTION_FIXUP]

---
 usr/include/arch/ia64/klibc/archconfig.h |  3 ++
 usr/klibc/SYSCALLS.def                   |  3 +-
 usr/klibc/arch/ia64/Kbuild               |  2 +-
 usr/klibc/arch/ia64/sigaction.c          | 50 ++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/usr/include/arch/ia64/klibc/archconfig.h b/usr/include/arch/ia64/klibc/archconfig.h
index adbd1ee4..9bf3c071 100644
--- a/usr/include/arch/ia64/klibc/archconfig.h
+++ b/usr/include/arch/ia64/klibc/archconfig.h
@@ -13,5 +13,8 @@
 #define _KLIBC_NO_MMU 0
 /* IA64 doesn't have sys_vfork, it has architecture-specific code */
 #define _KLIBC_REAL_VFORK 1
+/* Need to fix-up function pointers to function descriptor pointers
+ * in struct sigaction */
+#define _KLIBC_NEEDS_SIGACTION_FIXUP 1
 
 #endif				/* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 16ad3830..c8ac9e0d 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -206,9 +206,10 @@ ssize_t sendfile64,sendfile::sendfile(int, int, off_t *, size_t, off_t);
  * sanitizing <signal.h> for all architectures, sigh.  See <klibc/config.h>.
  */
 #if _KLIBC_USE_RT_SIG
-<!sparc,sparc64,alpha> int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
+<!sparc,sparc64,alpha,ia64> int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
 <sparc,sparc64> int rt_sigaction::____rt_sigaction(int, const struct sigaction *, struct sigaction *, void *, size_t);
 <alpha> int rt_sigaction::____rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t, void *);
+<ia64> int rt_sigaction::____rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
 int rt_sigsuspend::__rt_sigsuspend(const sigset_t *, size_t);
 int rt_sigpending::__rt_sigpending(sigset_t *, size_t);
 int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t);
diff --git a/usr/klibc/arch/ia64/Kbuild b/usr/klibc/arch/ia64/Kbuild
index 49070ff3..41b8ca06 100644
--- a/usr/klibc/arch/ia64/Kbuild
+++ b/usr/klibc/arch/ia64/Kbuild
@@ -2,7 +2,7 @@
 # klibc files for ia64
 #
 
-klib-y := vfork.o setjmp.o pipe.o syscall.o
+klib-y := vfork.o setjmp.o sigaction.o pipe.o syscall.o
 
 klib-y += ../../libgcc/__divdi3.o     ../../libgcc/__divsi3.o
 klib-y += ../../libgcc/__udivdi3.o    ../../libgcc/__udivsi3.o
diff --git a/usr/klibc/arch/ia64/sigaction.c b/usr/klibc/arch/ia64/sigaction.c
new file mode 100644
index 00000000..e512bdcd
--- /dev/null
+++ b/usr/klibc/arch/ia64/sigaction.c
@@ -0,0 +1,50 @@
+/*
+ * sigaction.c
+ */
+
+#include <signal.h>
+#include <sys/syscall.h>
+
+/* 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). */
+static struct {
+	uintptr_t entry;
+	uintptr_t gp;
+} signal_descriptors[_NSIG];
+
+__extern int ____rt_sigaction(int, const struct sigaction *, struct sigaction *,
+			      size_t);
+
+int __rt_sigaction(int sig, const struct sigaction *act,
+		   struct sigaction *oact, size_t size)
+{
+	uintptr_t old_entry;
+	int rv;
+
+	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) {
+		signal_descriptors[sig].entry = (uintptr_t)act->sa_handler;
+		act->sa_handler =
+			(__sighandler_t)(uintptr_t)&signal_descriptors[sig];
+	}
+
+	rv = ____rt_sigaction(sig, act, oact, size);
+
+	if (oact && oact->sa_handler != SIG_IGN &&
+	    oact->sa_handler != SIG_DFL) {
+		oact->sa_handler = (__sighandler_t)old_entry;
+	}
+
+	return rv;
+}


More information about the klibc mailing list