NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/50428: support SA_RESTORER flag for rt_sigaction(2) in Linux emulation
>Number: 50428
>Category: kern
>Synopsis: support SA_RESTORER flag for rt_sigaction(2) in Linux emulation
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Nov 14 10:10:00 +0000 2015
>Originator: Rin Okuyama
>Release: 7.99.21
>Organization:
Department of Physics, Tohoku University
>Environment:
NetBSD XXX 7.99.21 NetBSD 7.99.21 (GENERIC) #0: Sat Nov 14 16:22:15 JST 2015 root@XXX:XXX i386
>Description:
On Linux, SA_RESTORER flag for rt_sigaction(2) indicates that a signal
trampoline is provided by userland (usually by libc). Until now, this
flag has not been supported on ports other than amd64, which causes
EINVAL with some application on, e.g., i386.
The patch attached below enables SA_RESTORER flag on ports where Linux
supports it: arm, i386, and powerpc. It also fixes incorrect prototype
definitions of signal handler and trampoline on amd64.
Note that SA_RESTORER is not supported on alpha. On mips, it is no
longer supported by kernel, as it has never been used by libc (they
said).
Also note that I've checked this patch only on amd64 and i386.
>How-To-Repeat:
On i386, rt_sigaction(2) fails with EINVAL:
% ktrace /emul/linux/bin/bash
bash-4.2$ exit
% kdump
...
2515 2515 bash CALL rt_sigaction(SIGCHLD,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGCHLD,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGINT,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGINT,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGQUIT,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGQUIT,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGTERM,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGTERM,0xbfbff074,0xbfbff100,8)
2515 2515 bash RET rt_sigaction 0
2515 2515 bash CALL rt_sigaction(SIGHUP,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash NAMI "/stand/i386/7.99.21/modules/compat/compat.kmod"
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGINT,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGILL,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGTRAP,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGABRT,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGFPE,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGBUS,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGSEGV,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGSYS,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGPIPE,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGALRM,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGTERM,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGXCPU,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGXFSZ,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGVTALRM,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGUSR1,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigaction(SIGUSR2,0xbfbff064,0xbfbff0f0,8)
2515 2515 bash RET rt_sigaction -1 errno -22 Invalid argument
2515 2515 bash CALL rt_sigprocmask(0,0,0x80ea340,8)
2515 2515 bash RET rt_sigprocmask 0
...
After applying the patch below, rt_sigaction(2) works fine:
% ktrace /emul/linux/bash
bash-4.2$ exit
% kdump
...
557 557 bash CALL rt_sigaction(SIGCHLD,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGCHLD,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGINT,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGINT,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGQUIT,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGQUIT,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGTERM,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGTERM,0xbfbff5a4,0xbfbff630,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGHUP,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGINT,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGILL,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGTRAP,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGABRT,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGFPE,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGBUS,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGSEGV,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGSYS,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGPIPE,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGALRM,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGTERM,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGXCPU,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGXFSZ,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGVTALRM,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGUSR1,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigaction(SIGUSR2,0xbfbff594,0xbfbff620,8)
557 557 bash RET rt_sigaction 0
557 557 bash CALL rt_sigprocmask(0,0,0x80ea340,8)
557 557 bash RET rt_sigprocmask 0
...
>Fix:
--- ./src/sys/compat/linux/arch/alpha/linux_signal.h.orig 2015-11-14 15:17:42.000000000 +0900
+++ ./src/sys/compat/linux/arch/alpha/linux_signal.h 2015-11-14 15:57:34.000000000 +0900
@@ -92,13 +92,12 @@
#define LINUX_SA_RESETHAND 0x00000010
#define LINUX_SA_NOCLDWAIT 0x00000020
#define LINUX_SA_SIGINFO 0x00000040
-#define LINUX_SA_RESTORER 0x04000000
#define LINUX_SA_NOMASK LINUX_SA_NODEFER
#define LINUX_SA_ONESHOT LINUX_SA_RESETHAND
#define LINUX_SA_INTERRUPT 0x20000000 /* Ignore this */
-#define LINUX_SA_ALLBITS 0x2400007f
+#define LINUX_SA_ALLBITS 0x2000007f
#define LINUX_SIG_BLOCK 1
#define LINUX_SIG_UNBLOCK 2
--- ./src/sys/compat/linux/arch/amd64/linux_signal.h.orig 2015-11-14 15:40:06.000000000 +0900
+++ ./src/sys/compat/linux/arch/amd64/linux_signal.h 2015-11-14 15:56:58.000000000 +0900
@@ -103,24 +103,24 @@
/* struct old_sigaction32 in Linux; uses a 32 bit pointer for handlers */
struct linux_compat_old_sigaction {
- int linux_sa_handler;
+ linux_handler_t linux_sa_handler;
linux_old_sigset_t linux_sa_mask;
unsigned int linux_sa_flags;
- int linux_sa_restorer;
+ void (*linux_sa_restorer)(void);
};
/* Dummy declaration to avoid errors, unused */
struct linux_old_sigaction {
linux_handler_t linux_sa_handler;
unsigned long linux_sa_flags;
- linux_handler_t linux_sa_restorer;
+ void (*linux_sa_restorer)(void);
linux_sigset_t linux_sa_mask;
};
struct linux_sigaction {
linux_handler_t linux_sa_handler;
unsigned long linux_sa_flags;
- linux_handler_t linux_sa_restorer;
+ void (*linux_sa_restorer)(void);
linux_sigset_t linux_sa_mask;
};
--- ./src/sys/compat/linux/arch/mips/linux_signal.h.orig 2015-11-14 15:17:42.000000000 +0900
+++ ./src/sys/compat/linux/arch/mips/linux_signal.h 2015-11-14 15:59:39.000000000 +0900
@@ -104,15 +104,14 @@
#define LINUX_SA_NOCLDSTOP 0x00000001
#define LINUX_SA_SIGINFO 0x00000008
#define LINUX_SA_NOCLDWAIT 0x00010000
-#define LINUX_SA_RESTORER 0x04000000
#define LINUX_SA_ONSTACK 0x08000000
#define LINUX_SA_RESTART 0x10000000
-#define LINUX_SA_INTERRUPT 0x20000000
#define LINUX_SA_NODEFER 0x40000000
#define LINUX_SA_RESETHAND 0x80000000
#define LINUX_SA_NOMASK LINUX_SA_NODEFER
#define LINUX_SA_ONESHOT LINUX_SA_RESETHAND
-#define LINUX_SA_ALLBITS 0xfc010009 /* XXX from i386, not in mips. */
+#define LINUX_SA_ALLBITS 0xd8010009
+/* XXX LINUX_SA_RESTORER has been deprecated; not used any version of glibc */
#define LINUX_MINSIGSTKSZ 2048
--- ./src/sys/compat/linux/common/linux_signal.c.orig 2015-11-14 15:17:42.000000000 +0900
+++ ./src/sys/compat/linux/common/linux_signal.c 2015-11-14 16:50:48.000000000 +0900
@@ -331,7 +331,7 @@
int error, sig;
void *tramp = NULL;
int vers = 0;
-#if defined __amd64__
+#ifdef LINUX_SA_RESTORER
struct sigacts *ps = l->l_proc->p_sigacts;
#endif
@@ -354,11 +354,10 @@
sigemptyset(&obsa.sa_mask);
obsa.sa_flags = 0;
} else {
-#if defined __amd64__
- if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) {
- if ((tramp = nlsa.linux_sa_restorer) != NULL)
- vers = 2; /* XXX arch dependent */
- }
+#ifdef LINUX_SA_RESTORER
+ if ((nlsa.linux_sa_flags & LINUX_SA_RESTORER) &&
+ (tramp = nlsa.linux_sa_restorer) != NULL)
+ vers = 2;
#endif
error = sigaction1(l, linux_to_native_signo[sig],
@@ -371,7 +370,7 @@
if (SCARG(uap, osa)) {
native_to_linux_sigaction(&olsa, &obsa);
-#if defined __amd64__
+#ifdef LINUX_SA_RESTORER
if (ps->sa_sigdesc[sig].sd_vers != 0) {
olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp;
olsa.linux_sa_flags |= LINUX_SA_RESTORER;
Home |
Main Index |
Thread Index |
Old Index