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