public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h
@ 2018-02-12 12:42 Adhemerval Zanella
  2018-02-12 12:49 ` [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391) Adhemerval Zanella
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-12 12:42 UTC (permalink / raw)
  To: libc-alpha

Changes from previous version:

  - Fixed documentation issues pointed out by Rical Jasan.

--

This patch renames the nptl-signals.h header to internal-signals.h.
On Linux the definitions and functions are not only NPTL related, but
used for other POSIX definitions as well (for instance SIGTIMER for
posix times, SIGSETXID for id functions, and signal block/restore
helpers) and since generic functions will be places and used in generic
implementation it makes more sense to decouple it from NPTL.

Checked on x86_64-linux-gnu.

	* sysdeps/nptl/nptl-signals.h: Move to ...
	* sysdeps/generic/internal-signals.h: ... here.  Adjust internal
	comments.
	* sysdeps/unix/sysv/linux/internal-signals.h: Add include guards.
	(__nptl_is_internal_signal): Rename to __is_internal_signal.
	(__nptl_clear_internal_signals): Rename to __clear_internal_signals.
	* sysdeps/unix/sysv/linux/raise.c: Adjust nptl-signal.h to
	include-signals.h rename.
	* nptl/pthreadP.h: Likewise.
	* sysdeps/unix/sysv/linux/spawni.c (__spawni_child): Call
	__is_internal_signal instead of __nptl_is_internal_signal.

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
 ChangeLog                                                | 14 ++++++++++++++
 nptl/pthreadP.h                                          |  2 +-
 .../{nptl/nptl-signals.h => generic/internal-signals.h}  |  7 +------
 .../sysv/linux/{nptl-signals.h => internal-signals.h}    | 16 ++++++++++------
 sysdeps/unix/sysv/linux/raise.c                          |  2 +-
 sysdeps/unix/sysv/linux/spawni.c                         |  2 +-
 6 files changed, 28 insertions(+), 15 deletions(-)
 rename sysdeps/{nptl/nptl-signals.h => generic/internal-signals.h} (74%)
 rename sysdeps/unix/sysv/linux/{nptl-signals.h => internal-signals.h} (89%)

diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 583515f..075530c 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -32,7 +32,7 @@
 #include <atomic.h>
 #include <kernel-features.h>
 #include <errno.h>
-#include <nptl-signals.h>
+#include <internal-signals.h>
 
 
 /* Atomic operations on TLS memory.  */
diff --git a/sysdeps/nptl/nptl-signals.h b/sysdeps/generic/internal-signals.h
similarity index 74%
rename from sysdeps/nptl/nptl-signals.h
rename to sysdeps/generic/internal-signals.h
index e1275c7..01e5b75 100644
--- a/sysdeps/nptl/nptl-signals.h
+++ b/sysdeps/generic/internal-signals.h
@@ -1,4 +1,4 @@
-/* Special use of signals in NPTL internals.  Stub version.
+/* Special use of signals internally.  Stub version.
    Copyright (C) 2014-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -15,8 +15,3 @@
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
-
-/* This file can define the macros SIGCANCEL, SIGTIMER, and SIGSETXID to
-   signal numbers reserved by libpthread for those internal purposes.
-
-   Note that some code presumes SIGTIMER is the same as SIGCANCEL.  */
diff --git a/sysdeps/unix/sysv/linux/nptl-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
similarity index 89%
rename from sysdeps/unix/sysv/linux/nptl-signals.h
rename to sysdeps/unix/sysv/linux/internal-signals.h
index e789198..e007372 100644
--- a/sysdeps/unix/sysv/linux/nptl-signals.h
+++ b/sysdeps/unix/sysv/linux/internal-signals.h
@@ -1,4 +1,4 @@
-/* Special use of signals in NPTL internals.  Linux version.
+/* Special use of signals internally.  Linux version.
    Copyright (C) 2014-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,6 +16,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef __INTERNAL_SIGNALS_H
+# define __INTERNAL_SIGNALS_H
+
 #include <signal.h>
 #include <sigsetops.h>
 
@@ -35,17 +38,16 @@
 
 /* Return is sig is used internally.  */
 static inline int
-__nptl_is_internal_signal (int sig)
+__is_internal_signal (int sig)
 {
-  return (sig == SIGCANCEL) || (sig == SIGTIMER) || (sig == SIGSETXID);
+  return (sig == SIGCANCEL) || (sig == SIGSETXID);
 }
 
 /* Remove internal glibc signal from the mask.  */
 static inline void
-__nptl_clear_internal_signals (sigset_t *set)
+__clear_internal_signals (sigset_t *set)
 {
   __sigdelset (set, SIGCANCEL);
-  __sigdelset (set, SIGTIMER);
   __sigdelset (set, SIGSETXID);
 }
 
@@ -66,7 +68,7 @@ static inline int
 __libc_signal_block_app (sigset_t *set)
 {
   sigset_t allset = SIGALL_SET;
-  __nptl_clear_internal_signals (&allset);
+  __clear_internal_signals (&allset);
   INTERNAL_SYSCALL_DECL (err);
   return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set,
 			   _NSIG / 8);
@@ -83,3 +85,5 @@ __libc_signal_restore_set (const sigset_t *set)
 
 /* Used to communicate with signal handler.  */
 extern struct xid_command *__xidcmd attribute_hidden;
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c
index cb98f90..b05eae2 100644
--- a/sysdeps/unix/sysv/linux/raise.c
+++ b/sysdeps/unix/sysv/linux/raise.c
@@ -21,7 +21,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <nptl-signals.h>
+#include <internal-signals.h>
 
 int
 raise (int sig)
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
index 6b699a4..0391b9b 100644
--- a/sysdeps/unix/sysv/linux/spawni.c
+++ b/sysdeps/unix/sysv/linux/spawni.c
@@ -144,7 +144,7 @@ __spawni_child (void *arguments)
 	}
       else if (sigismember (&hset, sig))
 	{
-	  if (__nptl_is_internal_signal (sig))
+	  if (__is_internal_signal (sig))
 	    sa.sa_handler = SIG_IGN;
 	  else
 	    {
-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391)
  2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
@ 2018-02-12 12:49 ` Adhemerval Zanella
  2018-02-19 17:51   ` Adhemerval Zanella
  2018-02-12 12:53 ` [PATCH v4 3/4] linux: Consolidate sigaction implementation Adhemerval Zanella
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-12 12:49 UTC (permalink / raw)
  To: libc-alpha

This patch filters out the internal NPTL signals (SIGCANCEL/SIGTIMER and
SIGSETXID) from signal functions.  GLIBC on Linux requires both signals to
proper implement pthread cancellation, posix timers, and set*id posix
thread synchronization.

And not filtering out the internal signal is troublesome:

  - A conformant program on a architecture that does not filter out the
    signals might inadvertently disable pthread asynchronous cancellation,
    set*id synchronization or posix timers.

  - It might also to security issues if SIGSETXID is masked and set*id
    functions are called (some threads might have effective user or group
    id different from the rest).

The changes are basically:

  - Change __is_internal_signal to bool and used on all signal function
    that has a signal number as input.  Also for signal function which accepts
    signals sets (sigset_t) it assumes that canonical function were used to
    add/remove signals which lead to some input simplification.

  - Fix tst-sigset.c to avoid check for SIGCANCEL/SIGTIMER and SIGSETXID.
    It is rewritten to check each signal indidually and to check realtime
    signals using canonical macros.

  - Add generic __clear_internal_signals and __is_internal_signal
    version since both symbols are used on generic implementations.

  - Remove superflous sysdeps/nptl/sigfillset.c.

  - Remove superflous SIGTIMER handling on Linux __is_internal_signal
    since it is the same of SIGCANCEL.

  - Remove dangling define and obvious comment on nptl/sigaction.c.

Checked on x86_64-linux-gnu.

	[BZ #22391]
	* nptl/sigaction.c (__sigaction): Use __is_internal_signal to
	check for internal nptl signals.
	* signal/sigaddset.c (sigaddset): Likewise.
	* signal/sigdelset.c (sigdelset): Likewise.
	* sysdeps/posix/signal.c (__bsd_signal): Likewise.
	* sysdeps/posix/sigset.c (sigset): Call and check sigaddset return
	value.
	* signal/sigfillset.c (sigfillset): User __clear_internal_signals
	to filter out internal nptl signals.
	* signal/tst-sigset.c (do_test): Check ech signal indidually and
	also check realtime signals using standard macros.
	* sysdeps/nptl/nptl-signals.h (__clear_internal_signals,
	__is_internal_signal): New functions.
	* sysdeps/nptl/sigfillset.c: Remove file.
	* sysdeps/unix/sysv/linux/nptl-signals.h (__is_internal_signal):
	Change return to bool.
	(__clear_internal_signals): Remove SIGTIMER clean since it is
	equal to SIGCANEL on Linux.
	* sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Assume
	signal set was constructed using standard functions.
	* sysdeps/unix/sysv/linux/sigwait.c (do_sigtwait): Likewise.

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reported-by: Yury Norov <ynorov@caviumnetworks.com>
---
 ChangeLog                                  | 23 ++++++++
 nptl/sigaction.c                           | 14 +----
 signal/sigaction.c                         |  2 +-
 signal/sigaddset.c                         |  5 +-
 signal/sigdelset.c                         |  5 +-
 signal/sigfillset.c                        | 10 +---
 signal/tst-sigset.c                        | 92 ++++++++++++++++++++++--------
 sysdeps/generic/internal-signals.h         | 11 ++++
 sysdeps/nptl/sigfillset.c                  | 20 -------
 sysdeps/posix/signal.c                     |  5 +-
 sysdeps/posix/sigset.c                     | 10 +---
 sysdeps/unix/sysv/linux/internal-signals.h |  4 +-
 sysdeps/unix/sysv/linux/sigtimedwait.c     | 17 +-----
 13 files changed, 122 insertions(+), 96 deletions(-)
 delete mode 100644 sysdeps/nptl/sigfillset.c

diff --git a/nptl/sigaction.c b/nptl/sigaction.c
index ddf6f5e..79b6fdc 100644
--- a/nptl/sigaction.c
+++ b/nptl/sigaction.c
@@ -16,22 +16,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-
-/* This is no complete implementation.  The file is meant to be
-   included in the real implementation to provide the wrapper around
-   __libc_sigaction.  */
-
-#include <nptl/pthreadP.h>
-
-/* We use the libc implementation but we tell it to not allow
-   SIGCANCEL or SIGTIMER to be handled.  */
-#define LIBC_SIGACTION	1
-
+#include <internal-signals.h>
 
 int
 __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
 {
-  if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
+  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
     {
       __set_errno (EINVAL);
       return -1;
diff --git a/signal/sigaction.c b/signal/sigaction.c
index f761ca2..c99001a 100644
--- a/signal/sigaction.c
+++ b/signal/sigaction.c
@@ -24,7 +24,7 @@
 int
 __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
 {
-  if (sig <= 0 || sig >= NSIG)
+  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
     {
       __set_errno (EINVAL);
       return -1;
diff --git a/signal/sigaddset.c b/signal/sigaddset.c
index d310890..7238df4 100644
--- a/signal/sigaddset.c
+++ b/signal/sigaddset.c
@@ -17,13 +17,14 @@
 
 #include <errno.h>
 #include <signal.h>
-#include <sigsetops.h>
+#include <internal-signals.h>
 
 /* Add SIGNO to SET.  */
 int
 sigaddset (sigset_t *set, int signo)
 {
-  if (set == NULL || signo <= 0 || signo >= NSIG)
+  if (set == NULL || signo <= 0 || signo >= NSIG
+      || __is_internal_signal (signo))
     {
       __set_errno (EINVAL);
       return -1;
diff --git a/signal/sigdelset.c b/signal/sigdelset.c
index cd83dda..011978c 100644
--- a/signal/sigdelset.c
+++ b/signal/sigdelset.c
@@ -17,13 +17,14 @@
 
 #include <errno.h>
 #include <signal.h>
-#include <sigsetops.h>
+#include <internal-signals.h>
 
 /* Add SIGNO to SET.  */
 int
 sigdelset (sigset_t *set, int signo)
 {
-  if (set == NULL || signo <= 0 || signo >= NSIG)
+  if (set == NULL || signo <= 0 || signo >= NSIG
+      || __is_internal_signal (signo))
     {
       __set_errno (EINVAL);
       return -1;
diff --git a/signal/sigfillset.c b/signal/sigfillset.c
index e586fd9..83dd583 100644
--- a/signal/sigfillset.c
+++ b/signal/sigfillset.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+#include <internal-signals.h>
 
 /* Set all signals in SET.  */
 int
@@ -31,14 +32,7 @@ sigfillset (sigset_t *set)
 
   memset (set, 0xff, sizeof (sigset_t));
 
-  /* If the implementation uses a cancellation signal don't set the bit.  */
-#ifdef SIGCANCEL
-  __sigdelset (set, SIGCANCEL);
-#endif
-  /* Likewise for the signal to implement setxid.  */
-#ifdef SIGSETXID
-  __sigdelset (set, SIGSETXID);
-#endif
+  __clear_internal_signals (set);
 
   return 0;
 }
diff --git a/signal/tst-sigset.c b/signal/tst-sigset.c
index d47adcc..a2b764d 100644
--- a/signal/tst-sigset.c
+++ b/signal/tst-sigset.c
@@ -1,43 +1,85 @@
 /* Test sig*set functions.  */
 
 #include <signal.h>
-#include <stdio.h>
 
-#define TEST_FUNCTION do_test ()
+#include <support/check.h>
+
 static int
 do_test (void)
 {
-  int result = 0;
-  int sig = -1;
+  sigset_t set;
+  TEST_VERIFY (sigemptyset (&set) == 0);
 
-#define TRY(call)							      \
-  if (call)								      \
-    {									      \
-      printf ("%s (sig = %d): %m\n", #call, sig);			      \
-      result = 1;							      \
-    }									      \
-  else
+#define VERIFY(set, sig)			\
+  TEST_VERIFY (sigismember (&set, sig) == 0);	\
+  TEST_VERIFY (sigaddset (&set, sig) == 0);	\
+  TEST_VERIFY (sigismember (&set, sig) != 0);	\
+  TEST_VERIFY (sigdelset (&set, sig) == 0);	\
+  TEST_VERIFY (sigismember (&set, sig) == 0)
 
+  /* ISO C99 signals.  */
+  VERIFY (set, SIGINT);
+  VERIFY (set, SIGILL);
+  VERIFY (set, SIGABRT);
+  VERIFY (set, SIGFPE);
+  VERIFY (set, SIGSEGV);
+  VERIFY (set, SIGTERM);
 
-  sigset_t set;
-  TRY (sigemptyset (&set) != 0);
+  /* Historical signals specified by POSIX. */
+  VERIFY (set, SIGHUP);
+  VERIFY (set, SIGQUIT);
+  VERIFY (set, SIGTRAP);
+  VERIFY (set, SIGKILL);
+  VERIFY (set, SIGBUS);
+  VERIFY (set, SIGSYS);
+  VERIFY (set, SIGPIPE);
+  VERIFY (set, SIGALRM);
+
+  /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
+  VERIFY (set, SIGURG);
+  VERIFY (set, SIGSTOP);
+  VERIFY (set, SIGTSTP);
+  VERIFY (set, SIGCONT);
+  VERIFY (set, SIGCHLD);
+  VERIFY (set, SIGTTIN);
+  VERIFY (set, SIGTTOU);
+  VERIFY (set, SIGPOLL);
+  VERIFY (set, SIGXCPU);
+  VERIFY (set, SIGXFSZ);
+  VERIFY (set, SIGVTALRM);
+  VERIFY (set, SIGPROF);
+  VERIFY (set, SIGUSR1);
+  VERIFY (set, SIGUSR2);
+
+  /* Nonstandard signals found in all modern POSIX systems
+     (including both BSD and Linux).  */
+  VERIFY (set, SIGWINCH);
 
-#ifdef SIGRTMAX
-  int max_sig = SIGRTMAX;
-#else
-  int max_sig = NSIG - 1;
+  /* Arch-specific signals.  */
+#ifdef SIGEMT
+  VERIFY (set, SIGEMT);
+#endif
+#ifdef SIGLOST
+  VERIFY (set, SIGLOST);
+#endif
+#ifdef SIGINFO
+  VERIFY (set, SIGINFO);
+#endif
+#ifdef SIGSTKFLT
+  VERIFY (set, SIGSTKFLT);
+#endif
+#ifdef SIGPWR
+  VERIFY (set, SIGPWR);
 #endif
 
-  for (sig = 1; sig <= max_sig; ++sig)
+  /* Read-time signals (POSIX.1b real-time extensions).  If they are
+     supported SIGRTMAX value is greater than SIGRTMIN.  */
+  for (int rtsig = SIGRTMIN; rtsig <= SIGRTMAX; rtsig++)
     {
-      TRY (sigismember (&set, sig) != 0);
-      TRY (sigaddset (&set, sig) != 0);
-      TRY (sigismember (&set, sig) == 0);
-      TRY (sigdelset (&set, sig) != 0);
-      TRY (sigismember (&set, sig) != 0);
+      VERIFY (set, rtsig);
     }
 
-  return result;
+  return 0;
 }
 
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
diff --git a/sysdeps/generic/internal-signals.h b/sysdeps/generic/internal-signals.h
index 01e5b75..ab0b22e 100644
--- a/sysdeps/generic/internal-signals.h
+++ b/sysdeps/generic/internal-signals.h
@@ -15,3 +15,14 @@
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
+
+static inline void
+__clear_internal_signals (sigset_t *set)
+{
+}
+
+static inline bool
+__is_internal_signal (int sig)
+{
+  return false;
+}
diff --git a/sysdeps/nptl/sigfillset.c b/sysdeps/nptl/sigfillset.c
deleted file mode 100644
index 94a7680..0000000
--- a/sysdeps/nptl/sigfillset.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <nptl/pthreadP.h>
-
-#include <signal/sigfillset.c>
diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c
index a4a0875..8a135c7 100644
--- a/sysdeps/posix/signal.c
+++ b/sysdeps/posix/signal.c
@@ -18,8 +18,8 @@
 
 #include <errno.h>
 #include <signal.h>
-#include <string.h>	/* For the real memset prototype.  */
 #include <sigsetops.h>
+#include <internal-signals.h>
 
 sigset_t _sigintr attribute_hidden;		/* Set by siginterrupt.  */
 
@@ -31,7 +31,8 @@ __bsd_signal (int sig, __sighandler_t handler)
   struct sigaction act, oact;
 
   /* Check signal extents to protect __sigismember.  */
-  if (handler == SIG_ERR || sig < 1 || sig >= NSIG)
+  if (handler == SIG_ERR || sig < 1 || sig >= NSIG
+      || __is_internal_signal (sig))
     {
       __set_errno (EINVAL);
       return SIG_ERR;
diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c
index b62aa3c..6ab4a48 100644
--- a/sysdeps/posix/sigset.c
+++ b/sysdeps/posix/sigset.c
@@ -31,15 +31,9 @@ sigset (int sig, __sighandler_t disp)
   sigset_t set;
   sigset_t oset;
 
-  /* Check signal extents to protect __sigismember.  */
-  if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
-    {
-      __set_errno (EINVAL);
-      return SIG_ERR;
-    }
-
   __sigemptyset (&set);
-  __sigaddset (&set, sig);
+  if (sigaddset (&set, sig) < 0)
+    return SIG_ERR;
 
   if (disp == SIG_HOLD)
     {
diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
index e007372..5ff4cf8 100644
--- a/sysdeps/unix/sysv/linux/internal-signals.h
+++ b/sysdeps/unix/sysv/linux/internal-signals.h
@@ -21,6 +21,8 @@
 
 #include <signal.h>
 #include <sigsetops.h>
+#include <stdbool.h>
+#include <sysdep.h>
 
 /* The signal used for asynchronous cancelation.  */
 #define SIGCANCEL       __SIGRTMIN
@@ -37,7 +39,7 @@
 
 
 /* Return is sig is used internally.  */
-static inline int
+static inline bool
 __is_internal_signal (int sig)
 {
   return (sig == SIGCANCEL) || (sig == SIGSETXID);
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index 051a285..b4de885 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -24,21 +24,8 @@ int
 __sigtimedwait (const sigset_t *set, siginfo_t *info,
 		const struct timespec *timeout)
 {
-  sigset_t tmpset;
-  if (set != NULL
-      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
-	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
-    {
-      /* Create a temporary mask without the bit for SIGCANCEL set.  */
-      // We are not copying more than we have to.
-      memcpy (&tmpset, set, _NSIG / 8);
-      __sigdelset (&tmpset, SIGCANCEL);
-      __sigdelset (&tmpset, SIGSETXID);
-      set = &tmpset;
-    }
-
-    /* XXX The size argument hopefully will have to be changed to the
-       real size of the user-level sigset_t.  */
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
   int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
 
   /* The kernel generates a SI_TKILL code in si_code in case tkill is
-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v4 3/4] linux: Consolidate sigaction implementation
  2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
  2018-02-12 12:49 ` [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391) Adhemerval Zanella
@ 2018-02-12 12:53 ` Adhemerval Zanella
  2018-02-19 17:54   ` Adhemerval Zanella
  2018-02-12 14:02 ` [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) Adhemerval Zanella
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-12 12:53 UTC (permalink / raw)
  To: libc-alpha

This patch consolidates all Linux sigaction implementation on a default
one at sysdeps/unix/sysv/linux/sigaction.c.  The idea is remove redundant
code and simplify new ports addition by following the current generic
Linux User API (UAPI).

The UAPI for new ports defines a generic extensible sigaction struct as:

  struct sigaction
  {
    __sighandler_t sa_handler;
    unsigned long sa_flags;
  #ifdef SA_RESTORER
    void (*sa_restorer) (void);
  #endif
    sigset_t sa_mask;
  };

Where SA_RESTORER is just placed to compatibility reasons, news ports
should not add it.  A similar definition is used on generic
kernel_sigaction.h.

The user exported sigaction definition is not changed, so for most
architectures it requires an adjustment to kernel expected one for the
syscall.

The main changes are:

  - All architectures now define and use a kernel_sigaction struct meant
    for the syscall, even for the architectures where the user sigaction
    has the same layout of the kernel expected one (s390-64 and ia64).
    Although it requires more work for these architectures, it simplifies
    the generic implementation. Also, sigaction is hardly a hotspot where
    micro optimization would play an important role.

  - The generic kernel_sigaction definition is now aligned with expected
    UAPI one for newer ports, where SA_RESTORER and sa_restorer is not
    expected to be defined.  This means adding kernel_sigaction for
    current architectures that does define it (m68k, nios2, powerpc, s390,
    sh, sparc, and tile) and which rely on previous generic definition.

  - Remove old MIPS usage of sa_restorer.  This was removed since 2.6.27
    (2957c9e61ee9c - "[MIPS] IRIX: Goodbye and thanks for all the fish").

So for new ports the generic implementation should work if its uses
Linux UAPI.  If SA_RESTORER is still required (due some architecture
limitation), it should define its own kernel_sigaction.h, define it and
include generic header (assuming it still uses the default generic kernel
layout).

Checked on x86_64-linux-gnu, i686-linux-gnu, arm-linux-gnueabihf,
aarch64-linux-gnu, sparc64-linux-gnu, sparcv9-linux-gnu, powerpc-linux-gnu,
and powerpc64-linux-gnu.  I also check the build on all remaining affected
ABIs.

	* sysdeps/unix/sysv/linux/aarch64/sigaction.c: Use default Linux version
	as base implementation.
	* sysdeps/unix/sysv/linux/arm/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h: Add include guards,
	remove unrequired definitions and update comments.
	* sysdeps/unix/sysv/linux/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h: New file.
	* sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/kernel_sigaction: Likewise.
	* sysdeps/unix/sysv/linux/s390/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/tile/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/ia64/sigaction.c: Remove file.
	* sysdeps/unix/sysv/linux/mips/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c: Likewise.
	* sysdeps/unix/sysv/linux/sigaction.c: Add STUB, SET_SA_RESTORER,
	and RESET_SA_RESTORER hooks.

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
 ChangeLog                                          |  25 +++++
 sysdeps/unix/sysv/linux/aarch64/sigaction.c        |  58 ++---------
 sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h   |  21 ++--
 sysdeps/unix/sysv/linux/arm/sigaction.c            |  79 +++-----------
 sysdeps/unix/sysv/linux/i386/sigaction.c           |  76 +++-----------
 sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h    |   6 ++
 sysdeps/unix/sysv/linux/ia64/sigaction.c           |  45 --------
 sysdeps/unix/sysv/linux/kernel_sigaction.h         |  31 +++---
 sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h    |  22 ++++
 sysdeps/unix/sysv/linux/mips/kernel_sigaction.h    |  48 ++-------
 sysdeps/unix/sysv/linux/mips/sigaction.c           | 116 ---------------------
 sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h   |   8 ++
 sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h |   8 ++
 sysdeps/unix/sysv/linux/s390/kernel_sigaction.h    |  28 +++++
 sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c   |  43 --------
 sysdeps/unix/sysv/linux/sh/kernel_sigaction.h      |   8 ++
 sysdeps/unix/sysv/linux/sigaction.c                |  28 ++---
 sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h   |  10 ++
 sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c  |  41 +-------
 sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c  |  43 +-------
 sysdeps/unix/sysv/linux/tile/kernel_sigaction.h    |   9 ++
 sysdeps/unix/sysv/linux/x86_64/sigaction.c         |  61 ++---------
 22 files changed, 230 insertions(+), 584 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
 delete mode 100644 sysdeps/unix/sysv/linux/ia64/sigaction.c
 create mode 100644 sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
 delete mode 100644 sysdeps/unix/sysv/linux/mips/sigaction.c
 create mode 100644 sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
 create mode 100644 sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
 create mode 100644 sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
 create mode 100644 sysdeps/unix/sysv/linux/tile/kernel_sigaction.h

diff --git a/sysdeps/unix/sysv/linux/aarch64/sigaction.c b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
index 73f4eb7..83d5b4f 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sigaction.c
+++ b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
@@ -1,5 +1,4 @@
 /* Copyright (C) 1997-2018 Free Software Foundation, Inc.
-
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,55 +15,16 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
+/* Required for AArch32 compatibility. */
 #define SA_RESTORER	0x04000000
 
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
-#include <kernel_sigaction.h>
-
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int result;
-  struct kernel_sigaction kact;
-  struct kernel_sigaction koact;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-      kact.sa_flags = act->sa_flags;
-#ifdef HAVE_SA_RESTORER
-      if (kact.sa_flags & SA_RESTORER)
-	kact.sa_restorer = act->sa_restorer;
-#endif
-    }
+#define SET_SA_RESTORER(kact, act)				\
+ ({								\
+    if ((kact)->sa_flags & SA_RESTORER)				\
+      (kact)->sa_restorer = (act)->sa_restorer;			\
+ })
 
-  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
-			   act ? &kact : NULL,
-			   oact ? &koact : NULL, _NSIG / 8);
-  if (result >= 0 || errno != ENOSYS)
-    {
-      if (oact && result >= 0)
-	{
-	  oact->sa_handler = koact.k_sa_handler;
-	  memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-	  oact->sa_flags = koact.sa_flags;
-#ifdef HAVE_SA_RESTORER
-	  oact->sa_restorer = koact.sa_restorer;
-#endif
-	}
-    }
-  return result;
-}
-libc_hidden_def (__libc_sigaction)
+#define RESET_SA_RESTORER(act, kact)				\
+  (act)->sa_restorer = (kact)->sa_restorer;
 
-#include <nptl/sigaction.c>
+#include <sysdeps/unix/sysv/linux/sigaction.c>
diff --git a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
index 4c35d96..25180ff 100644
--- a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
+++ b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
@@ -1,15 +1,12 @@
-/* This is the sigaction struction from the Linux 2.1.20 kernel.  */
+#ifndef _KERNEL_SIGACTION_H
+# define _KERNEL_SIGACTION_H
 
-struct old_kernel_sigaction {
-	__sighandler_t k_sa_handler;
-	unsigned long sa_mask;
-	unsigned int sa_flags;
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction
+{
+  __sighandler_t k_sa_handler;
+  unsigned int sa_flags;
+  sigset_t sa_mask;
 };
 
-/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
-
-struct kernel_sigaction {
-	__sighandler_t k_sa_handler;
-	unsigned int sa_flags;
-	sigset_t sa_mask;
-};
+#endif
diff --git a/sysdeps/unix/sysv/linux/arm/sigaction.c b/sysdeps/unix/sysv/linux/arm/sigaction.c
index e4d80de..c828250 100644
--- a/sysdeps/unix/sysv/linux/arm/sigaction.c
+++ b/sysdeps/unix/sysv/linux/arm/sigaction.c
@@ -15,70 +15,25 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
-#include <kernel_sigaction.h>
-
 #define SA_RESTORER	0x04000000
 
 extern void __default_sa_restorer (void);
 extern void __default_rt_sa_restorer (void);
 
-/* When RT signals are in use we need to use a different return stub.  */
-#define choose_restorer(flags)					\
-  (flags & SA_SIGINFO) ? __default_rt_sa_restorer		\
-  : __default_sa_restorer
-
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int result;
-
-  struct kernel_sigaction kact, koact;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-      kact.sa_flags = act->sa_flags;
-#ifdef HAVE_SA_RESTORER
-      if (kact.sa_flags & SA_RESTORER)
-	kact.sa_restorer = act->sa_restorer;
-      else
-	{
-	  kact.sa_restorer = choose_restorer (kact.sa_flags);
-	  kact.sa_flags |= SA_RESTORER;
-	}
-#endif
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
-			   act ? &kact : NULL,
-			   oact ? &koact : NULL, _NSIG / 8);
-
-  if (oact && result >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-      oact->sa_flags = koact.sa_flags;
-#ifdef HAVE_SA_RESTORER
-      oact->sa_restorer = koact.sa_restorer;
-#endif
-    }
-  return result;
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
+#define SET_SA_RESTORER(kact, act)				\
+ ({								\
+   if ((kact)->sa_flags & SA_RESTORER)				\
+     (kact)->sa_restorer = (act)->sa_restorer;			\
+   else								\
+     {								\
+       (kact)->sa_restorer = ((kact)->sa_flags & SA_SIGINFO)	\
+			     ? __default_rt_sa_restorer		\
+			     : __default_sa_restorer;		\
+       (kact)->sa_flags |= SA_RESTORER;				\
+     }								\
+ })
+
+#define RESET_SA_RESTORER(act, kact)				\
+  (act)->sa_restorer = (kact)->sa_restorer;
+
+#include <sysdeps/unix/sysv/linux/sigaction.c>
diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
index a5eb9e0..137c73b 100644
--- a/sysdeps/unix/sysv/linux/i386/sigaction.c
+++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
@@ -16,78 +16,28 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-#include <errno.h>
-#include <stddef.h>
 #include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
 #include <ldsodefs.h>
 
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
-#include <kernel_sigaction.h>
-
-/* We do not globally define the SA_RESTORER flag so do it here.  */
 #define SA_RESTORER 0x04000000
 
-
-/* Using the hidden attribute here does not change the code but it
-   helps to avoid warnings.  */
-#ifdef __NR_rt_sigaction
 extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
-#endif
 extern void restore (void) asm ("__restore") attribute_hidden;
 
+#define SET_SA_RESTORER(kact, act)				\
+  ({								\
+     if (GLRO(dl_sysinfo_dso) == NULL)				\
+       {							\
+	 (kact)->sa_flags |= SA_RESTORER;			\
+         (kact)->sa_restorer = (((act)->sa_flags & SA_SIGINFO)	\
+			       ? &restore_rt : &restore);	\
+       }							\
+  })
 
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int result;
-
-  struct kernel_sigaction kact, koact;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      kact.sa_flags = act->sa_flags;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-
-      if (GLRO(dl_sysinfo_dso) == NULL)
-	{
-	  kact.sa_flags |= SA_RESTORER;
-
-	  kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
-			      ? &restore_rt : &restore);
-	}
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  INTERNAL_SYSCALL_DECL (err);
-  result = INTERNAL_SYSCALL (rt_sigaction, err, 4,
-			     sig, act ? &kact : NULL,
-			     oact ? &koact : NULL, _NSIG / 8);
-  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
-     return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
-								       err));
-  else if (oact && result >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-      oact->sa_flags = koact.sa_flags;
-      oact->sa_restorer = koact.sa_restorer;
-    }
-  return result;
-}
-libc_hidden_def (__libc_sigaction)
+#define RESET_SA_RESTORER(act, kact) \
+  (act)->sa_restorer = (kact)->sa_restorer
 
-#include <nptl/sigaction.c>
+#include <sysdeps/unix/sysv/linux/sigaction.c>
 
 /* NOTE: Please think twice before making any changes to the bits of
    code below.  GDB needs some intimate knowledge about it to
@@ -108,10 +58,8 @@ asm						\
    "	int  $0x80"				\
    );
 
-#ifdef __NR_rt_sigaction
 /* The return code for realtime-signals.  */
 RESTORE (restore_rt, __NR_rt_sigreturn)
-#endif
 
 /* For the boring old signals.  */
 #undef RESTORE2
diff --git a/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
new file mode 100644
index 0000000..05813db
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
@@ -0,0 +1,6 @@
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction {
+        __sighandler_t k_sa_handler;
+        unsigned long sa_flags;
+        sigset_t sa_mask;               /* mask last for extensibility */
+};
diff --git a/sysdeps/unix/sysv/linux/ia64/sigaction.c b/sysdeps/unix/sysv/linux/ia64/sigaction.c
deleted file mode 100644
index e7fb8cd..0000000
--- a/sysdeps/unix/sysv/linux/ia64/sigaction.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Linux/IA64 specific sigaction
-   Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Linux/ia64 only has rt signals, thus we do not even want to try falling
-   back to the old style signals as the default Linux handler does. */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The variable is shared between all wrappers around signal handling
-   functions which have RT equivalents.  This is the definition.  */
-
-
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
diff --git a/sysdeps/unix/sysv/linux/kernel_sigaction.h b/sysdeps/unix/sysv/linux/kernel_sigaction.h
index d005cbc..2dbec08 100644
--- a/sysdeps/unix/sysv/linux/kernel_sigaction.h
+++ b/sysdeps/unix/sysv/linux/kernel_sigaction.h
@@ -1,19 +1,20 @@
-/* This is the sigaction structure from the Linux 2.1.20 kernel.  */
+#ifndef _KERNEL_SIGACTION_H
+# define _KERNEL_SIGACTION_H
 
-#define HAVE_SA_RESTORER
-
-struct old_kernel_sigaction {
-	__sighandler_t k_sa_handler;
-	unsigned long sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction
+{
+  __sighandler_t k_sa_handler;
+  unsigned long sa_flags;
+#ifdef SA_RESTORER
+  void (*sa_restorer) (void);
+#endif
+  sigset_t sa_mask;
 };
 
-/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
+#ifndef SA_RESTORER
+# define SET_SA_RESTORER(kact, act)
+# define RESET_SA_RESTORER(act, kact)
+#endif
 
-struct kernel_sigaction {
-	__sighandler_t k_sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
-	sigset_t sa_mask;
-};
+#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
new file mode 100644
index 0000000..54972fe
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
@@ -0,0 +1,22 @@
+#ifndef _KERNEL_SIGACTION_H
+# define _KERNEL_SIGACTION_H
+
+#include <signal.h>
+
+#define SA_RESTORER 0x04000000
+
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction
+{
+  __sighandler_t k_sa_handler;
+  sigset_t sa_mask;
+  unsigned long sa_flags;
+  void (*sa_restorer) (void);
+};
+
+#define SET_SA_RESTORER(kact, act)			\
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)			\
+  (act)->sa_restorer = (kact)->sa_restorer
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
index b6f52cc..beef976 100644
--- a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
+++ b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
@@ -1,40 +1,12 @@
-/* This is the sigaction structure from the Linux 2.1.24 kernel.  */
-
-#include <sgidefs.h>
-
-#define HAVE_SA_RESTORER
-
-struct old_kernel_sigaction {
-	unsigned int	sa_flags;
-	__sighandler_t	k_sa_handler;
-	unsigned long	sa_mask;
-	unsigned int    __pad0[3]; /* reserved, keep size constant */
-
-	/* Abi says here follows reserved int[2] */
-	void		(*sa_restorer)(void);
-#if (_MIPS_SZPTR < 64)
-	/*
-	 * For 32 bit code we have to pad struct sigaction to get
-	 * constant size for the ABI
-	 */
-	int		pad1[1]; /* reserved */
-#endif
+#ifndef _KERNEL_SIGACTION_H
+# define _KERNEL_SIGACTION_H
+
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction
+{
+  unsigned int    sa_flags;
+  __sighandler_t  k_sa_handler;
+  sigset_t        sa_mask;
 };
 
-
-#define _KERNEL_NSIG	       128
-#define _KERNEL_NSIG_BPW       _MIPS_SZLONG
-#define _KERNEL_NSIG_WORDS     (_KERNEL_NSIG / _KERNEL_NSIG_BPW)
-
-typedef struct {
-	unsigned long sig[_KERNEL_NSIG_WORDS];
-} kernel_sigset_t;
-
-/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
-struct kernel_sigaction {
-	unsigned int	sa_flags;
-	__sighandler_t	k_sa_handler;
-	kernel_sigset_t	sa_mask;
-	void		(*sa_restorer)(void);
-	int		s_resv[1]; /* reserved */
-};
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/sigaction.c b/sysdeps/unix/sysv/linux/mips/sigaction.c
deleted file mode 100644
index 008b688..0000000
--- a/sysdeps/unix/sysv/linux/mips/sigaction.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <sgidefs.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include <sgidefs.h>
-
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
-#include <kernel_sigaction.h>
-
-#if _MIPS_SIM != _ABIO32
-
-# ifdef __NR_rt_sigreturn
-static void restore_rt (void) asm ("__restore_rt");
-# endif
-# ifdef __NR_sigreturn
-static void restore (void) asm ("__restore");
-# endif
-#endif
-
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int result;
-
-  struct kernel_sigaction kact, koact;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kernel_sigset_t));
-      kact.sa_flags = act->sa_flags;
-#ifdef HAVE_SA_RESTORER
-# if _MIPS_SIM == _ABIO32
-      kact.sa_restorer = act->sa_restorer;
-# else
-      kact.sa_restorer = &restore_rt;
-# endif
-#endif
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.	*/
-  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
-			   act ? &kact : NULL,
-			   oact ? &koact : NULL,
-			   sizeof (kernel_sigset_t));
-
-  if (oact && result >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask,
-	      sizeof (kernel_sigset_t));
-      oact->sa_flags = koact.sa_flags;
-#ifdef HAVE_SA_RESTORER
-      oact->sa_restorer = koact.sa_restorer;
-#endif
-    }
-  return result;
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
-
-
-/* NOTE: Please think twice before making any changes to the bits of
-   code below.  GDB needs some intimate knowledge about it to
-   recognize them as signal trampolines, and make backtraces through
-   signal handlers work right.  Important are both the names
-   (__restore_rt) and the exact instruction sequence.
-   If you ever feel the need to make any changes, please notify the
-   appropriate GDB maintainer.  */
-
-#define RESTORE(name, syscall) RESTORE2 (name, syscall)
-#define RESTORE2(name, syscall) \
-asm						\
-  (						\
-   ".align 4\n"					\
-   "__" #name ":\n"				\
-   "	li $2, " #syscall "\n"			\
-   "	syscall\n"				\
-   );
-
-/* The return code for realtime-signals.  */
-#if _MIPS_SIM != _ABIO32
-# ifdef __NR_rt_sigreturn
-RESTORE (restore_rt, __NR_rt_sigreturn)
-# endif
-# ifdef __NR_sigreturn
-RESTORE (restore, __NR_sigreturn)
-# endif
-#endif
diff --git a/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
new file mode 100644
index 0000000..4ada322
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
@@ -0,0 +1,8 @@
+/* NIOS2 uses the generic Linux UAPI but defines SA_RESTORER.  */
+#define SA_RESTORER 0x04000000
+#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
new file mode 100644
index 0000000..c5213f2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
@@ -0,0 +1,8 @@
+/* powerpc kernel sigaction is similar to generic Linux UAPI one.  */
+#define SA_RESTORER 0x04000000
+#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
new file mode 100644
index 0000000..a8beaf7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
@@ -0,0 +1,28 @@
+#include <bits/types/siginfo_t.h>
+
+#define SA_RESTORER	0x04000000
+
+/* This is the sigaction structure from the Linux 3.2 kernel.  */
+struct kernel_sigaction
+{
+  union
+  {
+    __sighandler_t _sa_handler;
+    void (*_sa_sigaction)(int, siginfo_t *, void *);
+  } _u;
+#define k_sa_handler _u._sa_handler
+#ifndef __s390x__
+  sigset_t sa_mask;
+  unsigned long sa_flags;
+  void (*sa_restorer)(void);
+#else
+  unsigned long sa_flags;
+  void (*sa_restorer)(void);
+  sigset_t sa_mask;
+#endif
+};
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c b/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
deleted file mode 100644
index c13927c..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* 64 bit Linux for S/390 only has rt signals, thus we do not even want to try
-   falling back to the old style signals as the default Linux handler does. */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The variable is shared between all wrappers around signal handling
-   functions which have RT equivalents.  This is the definition.  */
-
-
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
diff --git a/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
new file mode 100644
index 0000000..7ebcd08
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
@@ -0,0 +1,8 @@
+/* SH uses the generic Linux UAPI but defines SA_RESTORER.  */
+#define SA_RESTORER 0x04000000
+#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c
index 40a311a..0e6851a 100644
--- a/sysdeps/unix/sysv/linux/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sigaction.c
@@ -22,11 +22,19 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
+/* New ports should not define the obsolete SA_RESTORER, however some
+   architecture requires for compat mode and/or due old ABI.  */
 #include <kernel_sigaction.h>
 
+#ifndef SA_RESTORER
+# define SET_SA_RESTORER(kact, act)
+# define RESET_SA_RESTORER(act, kact)
+#endif
+
+/* SPARC passes the restore function as an argument to rt_sigaction.  */
+#ifndef STUB
+# define STUB(act)
+#endif
 
 /* If ACT is not NULL, change the action for SIG to *ACT.
    If OACT is not NULL, put the old action for SIG in *OACT.  */
@@ -42,25 +50,21 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
       kact.k_sa_handler = act->sa_handler;
       memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
       kact.sa_flags = act->sa_flags;
-#ifdef HAVE_SA_RESTORER
-      kact.sa_restorer = act->sa_restorer;
-#endif
+      SET_SA_RESTORER (&kact, act);
     }
 
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
-			   act ? &kact : NULL,
-			   oact ? &koact : NULL, _NSIG / 8);
+  result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
+				act ? &kact : NULL,
+				oact ? &koact : NULL, STUB(act) _NSIG / 8);
 
   if (oact && result >= 0)
     {
       oact->sa_handler = koact.k_sa_handler;
       memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
       oact->sa_flags = koact.sa_flags;
-#ifdef HAVE_SA_RESTORER
-      oact->sa_restorer = koact.sa_restorer;
-#endif
+      RESET_SA_RESTORER (oact, &koact);
     }
   return result;
 }
diff --git a/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
new file mode 100644
index 0000000..bee7e9c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
@@ -0,0 +1,10 @@
+/* SPARC 'struct __new_sigaction' is similar to generic Linux UAPI with
+   a sa_restorer field, even though function is passed as an argument
+   to rt_sigaction syscall.  */
+#define SA_RESTORER 0x04000000
+#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = NULL
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
index 204a5d8..c1d8f45 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
@@ -27,43 +27,12 @@
 static void __rt_sigreturn_stub (void);
 static void __sigreturn_stub (void);
 
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  struct kernel_sigaction kact, koact;
-  unsigned long stub = 0;
-  int ret;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-      if (((kact.sa_flags = act->sa_flags) & SA_SIGINFO) != 0)
-	stub = (unsigned long) &__rt_sigreturn_stub;
-      else
-	stub = (unsigned long) &__sigreturn_stub;
-      stub -= 8;
-      kact.sa_restorer = NULL;
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  ret = INLINE_SYSCALL (rt_sigaction, 5, sig, act ? &kact : 0,
-			oact ? &koact : 0, stub, _NSIG / 8);
-
-  if (oact && ret >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-      oact->sa_flags = koact.sa_flags;
-      oact->sa_restorer = koact.sa_restorer;
-    }
-  return ret;
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
+#define STUB(act) \
+  ((unsigned long)((act->sa_flags & SA_SIGINFO)		\
+		    ? &__rt_sigreturn_stub		\
+		    : &__sigreturn_stub) - 8),
 
+#include <sysdeps/unix/sysv/linux/sigaction.c>
 
 static
 inhibit_stack_protector
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
index 73cda4c..cfbbc6e 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
@@ -21,50 +21,13 @@
 #include <string.h>
 #include <syscall.h>
 #include <sysdep.h>
-#include <sys/signal.h>
-#include <errno.h>
-
-#include <kernel_sigaction.h>
-
-/* SPARC 64bit userland requires a kernel that has rt signals anyway. */
 
 static void __rt_sigreturn_stub (void);
 
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int ret;
-  struct kernel_sigaction kact, koact;
-  unsigned long stub = ((unsigned long) &__rt_sigreturn_stub) - 8;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-      kact.sa_flags = act->sa_flags;
-      kact.sa_restorer = NULL;
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  ret = INLINE_SYSCALL (rt_sigaction, 5, sig,
-			act ? &kact : 0,
-			oact ? &koact : 0, stub, _NSIG / 8);
-
-  if (oact && ret >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-      oact->sa_flags = koact.sa_flags;
-      oact->sa_restorer = koact.sa_restorer;
-    }
-
-  return ret;
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
+#define STUB(act) \
+  (((unsigned long) &__rt_sigreturn_stub) - 8),
 
+#include <sysdeps/unix/sysv/linux/sigaction.c>
 
 static
 inhibit_stack_protector
diff --git a/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
new file mode 100644
index 0000000..a943d52
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
@@ -0,0 +1,9 @@
+/* tile kernel sigaction is similar to generic Linux UAPI one
+   and SA_RESTORER is used only for binary compatibility.  */
+#define SA_RESTORER 0x04000000
+#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
+
+#define SET_SA_RESTORER(kact, act)             \
+  (kact)->sa_restorer = (act)->sa_restorer
+#define RESET_SA_RESTORER(act, kact)           \
+  (act)->sa_restorer = (kact)->sa_restorer
diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
index 2f7459f..4e6d9cc 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c
+++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
@@ -16,65 +16,20 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-#include <errno.h>
-#include <stddef.h>
 #include <signal.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* The difference here is that the sigaction structure used in the
-   kernel is not the same as we use in the libc.  Therefore we must
-   translate it here.  */
-#include <kernel_sigaction.h>
-
-#include "ucontext_i.h"
-
-/* We do not globally define the SA_RESTORER flag so do it here.  */
 #define SA_RESTORER 0x04000000
+#include <kernel_sigaction.h>
 
-/* Using the hidden attribute here does not change the code but it
-   helps to avoid warnings.  */
 extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
 
+#define SET_SA_RESTORER(kact, act)			\
+  (kact)->sa_flags = (act)->sa_flags | SA_RESTORER;	\
+  (kact)->sa_restorer = &restore_rt
 
-/* If ACT is not NULL, change the action for SIG to *ACT.
-   If OACT is not NULL, put the old action for SIG in *OACT.  */
-int
-__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
-{
-  int result;
-  struct kernel_sigaction kact, koact;
-
-  if (act)
-    {
-      kact.k_sa_handler = act->sa_handler;
-      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
-      kact.sa_flags = act->sa_flags | SA_RESTORER;
-
-      kact.sa_restorer = &restore_rt;
-    }
-
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  result = INLINE_SYSCALL (rt_sigaction, 4,
-			   sig, act ? &kact : NULL,
-			   oact ? &koact : NULL, _NSIG / 8);
-  if (oact && result >= 0)
-    {
-      oact->sa_handler = koact.k_sa_handler;
-      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
-      oact->sa_flags = koact.sa_flags;
-      oact->sa_restorer = koact.sa_restorer;
-    }
-  return result;
-}
-libc_hidden_def (__libc_sigaction)
-
-#include <nptl/sigaction.c>
+#define RESET_SA_RESTORER(act, kact) 			\
+  (act)->sa_restorer = (kact)->sa_restorer
 
+#include <sysdeps/unix/sysv/linux/sigaction.c>
 
 /* NOTE: Please think twice before making any changes to the bits of
    code below.  GDB needs some intimate knowledge about it to
@@ -93,6 +48,8 @@ libc_hidden_def (__libc_sigaction)
    a bit tricky.  We don't use the gas cfi directives, so that we can
    reliably add .cfi_signal_frame.  */
 
+#include "ucontext_i.h"
+
 #define do_cfa_expr						\
   "	.byte 0x0f\n"		/* DW_CFA_def_cfa_expression */	\
   "	.uleb128 2f-1f\n"	/* length */			\
-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269)
  2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
  2018-02-12 12:49 ` [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391) Adhemerval Zanella
  2018-02-12 12:53 ` [PATCH v4 3/4] linux: Consolidate sigaction implementation Adhemerval Zanella
@ 2018-02-12 14:02 ` Adhemerval Zanella
  2018-02-19 18:08   ` Adhemerval Zanella
  2018-02-19 18:23   ` H.J. Lu
  2018-02-19 17:51 ` [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
  2018-02-20 13:00 ` Florian Weimer
  4 siblings, 2 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-12 14:02 UTC (permalink / raw)
  To: libc-alpha

This patch fixes the i386 sa_restorer field initialization for sigaction
syscall for kernel with vDSO.  As described in bug report, x86_32 Linux
(and compat on x86_64) interprets SA_RESTORER clear with nonzero
sa_restorer as a request for stack switching if the SS segment is 'funny'
This means that anything that tries to mix glibc's signal handling with
segmentation (for instance through modify_ldt syscall) is randomly broken
depending on what values lands in sa_restorer.

The testcase added  is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
more specifically in do_multicpu_tests function.  The main changes are:

  - C11 atomics instead of plain access.

  - Remove x86_64 support which simplifies the syscall handling and fallbacks.

  - Replicate only the test required to trigger the issue.

(I added some comments of my understanding of how the testcase is triggering
the issue, so if someone with more x86 knowledge could check if I get this
right I will be grateful)

Checked on i686-linux-gnu.

	[BZ #21269]
	* sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269.
	* sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear
	sa_restorer for vDSO case.
	* sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file.

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
 ChangeLog                                  |   6 +
 sysdeps/unix/sysv/linux/i386/Makefile      |   3 +
 sysdeps/unix/sysv/linux/i386/sigaction.c   |   2 +
 sysdeps/unix/sysv/linux/i386/tst-bz21269.c | 233 +++++++++++++++++++++++++++++
 4 files changed, 244 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/i386/tst-bz21269.c

diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 4080b8c..da716e2 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -3,6 +3,9 @@ default-abi := 32
 
 ifeq ($(subdir),misc)
 sysdep_routines += ioperm iopl vm86
+
+tests += tst-bz21269
+$(objpfx)tst-bz21269: $(shared-thread-library)
 endif
 
 ifeq ($(subdir),elf)
diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
index 137c73b..df9fa0c 100644
--- a/sysdeps/unix/sysv/linux/i386/sigaction.c
+++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
@@ -32,6 +32,8 @@ extern void restore (void) asm ("__restore") attribute_hidden;
          (kact)->sa_restorer = (((act)->sa_flags & SA_SIGINFO)	\
 			       ? &restore_rt : &restore);	\
        }							\
+     else							\
+       (kact)->sa_restorer = NULL;				\
   })
 
 #define RESET_SA_RESTORER(act, kact) \
diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
new file mode 100644
index 0000000..353e365
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
@@ -0,0 +1,233 @@
+/* Test for i386 sigaction sa_restorer handling (BZ#21269)
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
+   more specifically in do_multicpu_tests function.  The main changes
+   are:
+
+   - C11 atomics instead of plain access.
+   - Remove x86_64 support which simplifies the syscall handling
+     and fallbacks.
+   - Replicate only the test required to trigger the issue for the
+     BZ#21269.  */
+
+#include <stdatomic.h>
+
+#include <asm/ldt.h>
+#include <linux/futex.h>
+
+#include <setjmp.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+static int
+xset_thread_area (struct user_desc *u_info)
+{
+  long ret = syscall (SYS_set_thread_area, u_info);
+  TEST_VERIFY_EXIT (ret == 0);
+  return ret;
+}
+
+static void
+xmodify_ldt (int func, const void *ptr, unsigned long bytecount)
+{
+  TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0);
+}
+
+static int
+futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2,
+	int val3)
+{
+  return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
+}
+
+static void
+xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags)
+{
+  struct sigaction sa = { 0 };
+  sa.sa_sigaction = handler;
+  sa.sa_flags = SA_SIGINFO | flags;
+  TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0);
+  TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0);
+}
+
+static jmp_buf jmpbuf;
+
+static void
+sigsegv_handler (int sig, siginfo_t *info, void *ctx_void)
+{
+  siglongjmp (jmpbuf, 1);
+}
+
+/* Points to an array of 1024 ints, each holding its own index.  */
+static const unsigned int *counter_page;
+static struct user_desc *low_user_desc;
+static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry.  */
+static int gdt_entry_num;
+
+static void
+setup_counter_page (void)
+{
+  long page_size = sysconf (_SC_PAGE_SIZE);
+  TEST_VERIFY_EXIT (page_size > 0);
+  unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE,
+			      MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
+  for (int i = 0; i < (page_size / sizeof (unsigned int)); i++)
+    page[i] = i;
+  counter_page = page;
+}
+
+static void
+setup_low_user_desc (void)
+{
+  low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc),
+			 PROT_READ | PROT_WRITE,
+			 MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
+
+  low_user_desc->entry_number    = -1;
+  low_user_desc->base_addr       = (unsigned long) &counter_page[1];
+  low_user_desc->limit           = 0xffff;
+  low_user_desc->seg_32bit       = 1;
+  low_user_desc->contents        = 0;
+  low_user_desc->read_exec_only  = 0;
+  low_user_desc->limit_in_pages  = 1;
+  low_user_desc->seg_not_present = 0;
+  low_user_desc->useable         = 0;
+
+  xset_thread_area (low_user_desc);
+
+  low_user_desc_clear = low_user_desc + 1;
+  low_user_desc_clear->entry_number = gdt_entry_num;
+  low_user_desc_clear->read_exec_only = 1;
+  low_user_desc_clear->seg_not_present = 1;
+}
+
+/* Possible values of futex:
+   0: thread is idle.
+   1: thread armed.
+   2: thread should clear LDT entry 0.
+   3: thread should exit.  */
+static atomic_uint ftx;
+
+static void *
+threadproc (void *ctx)
+{
+  while (1)
+    {
+      futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
+      while (atomic_load (&ftx) != 2)
+	{
+	  if (atomic_load (&ftx) >= 3)
+	    return NULL;
+	}
+
+      /* clear LDT entry 0.  */
+      const struct user_desc desc = { 0 };
+      xmodify_ldt (1, &desc, sizeof (desc));
+
+      /* If ftx == 2, set it to zero,  If ftx == 100, quit.  */
+      if (atomic_fetch_add (&ftx, -2) != 2)
+	return NULL;
+    }
+}
+
+
+/* As described in testcase, for historical reasons x86_32 Linux (and compat
+   on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a
+   request for stack switching if the SS segment is 'funny' (this is default
+   scenario for vDSO system).  This means that anything that tries to mix
+   signal handling with segmentation should explicit clear the sa_restorer.
+
+   This testcase check if sigaction in fact does it by changing the local
+   descriptor table (LDT) through the modify_ldt syscall and triggering
+   a synchronous segfault on iret fault by trying to install an invalid
+   segment.  With a correct zeroed sa_restorer it should not trigger an
+   'real' SEGSEGV and allows the siglongjmp in signal handler.  */
+
+static int
+do_test (void)
+{
+  setup_counter_page ();
+  setup_low_user_desc ();
+
+  pthread_t thread;
+  unsigned short orig_ss;
+
+  xsethandler (SIGSEGV, sigsegv_handler, 0);
+  /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults.  */
+  xsethandler (SIGILL, sigsegv_handler, 0);
+
+  thread = xpthread_create (0, threadproc, 0);
+
+  asm volatile ("mov %%ss, %0" : "=rm" (orig_ss));
+
+  for (int i = 0; i < 5; i++)
+    {
+      if (sigsetjmp (jmpbuf, 1) != 0)
+	continue;
+
+      /* Make sure the thread is ready after the last test. */
+      while (atomic_load (&ftx) != 0)
+	;
+
+      struct user_desc desc = {
+	.entry_number       = 0,
+	.base_addr          = 0,
+	.limit              = 0xffff,
+	.seg_32bit          = 1,
+	.contents           = 0,
+	.read_exec_only     = 0,
+	.limit_in_pages     = 1,
+	.seg_not_present    = 0,
+	.useable            = 0
+      };
+
+      xmodify_ldt (0x11, &desc, sizeof (desc));
+
+      /* Arm the thread.  */
+      ftx = 1;
+      futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+
+      asm volatile ("mov %0, %%ss" : : "r" (0x7));
+
+      /* Fire up thread modify_ldt call.  */
+      atomic_store (&ftx, 2);
+
+      while (atomic_load (&ftx) != 0)
+	;
+
+      /* On success, modify_ldt will segfault us synchronously and we will
+	 escape via siglongjmp.  */
+      support_record_failure ();
+    }
+
+  atomic_store (&ftx, 100);
+  futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+
+  xpthread_join (thread);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391)
  2018-02-12 12:49 ` [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391) Adhemerval Zanella
@ 2018-02-19 17:51   ` Adhemerval Zanella
  2018-04-03 14:24     ` Adhemerval Zanella
  0 siblings, 1 reply; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-19 17:51 UTC (permalink / raw)
  To: libc-alpha

Ping.

On 12/02/2018 10:42, Adhemerval Zanella wrote:
> This patch filters out the internal NPTL signals (SIGCANCEL/SIGTIMER and
> SIGSETXID) from signal functions.  GLIBC on Linux requires both signals to
> proper implement pthread cancellation, posix timers, and set*id posix
> thread synchronization.
> 
> And not filtering out the internal signal is troublesome:
> 
>   - A conformant program on a architecture that does not filter out the
>     signals might inadvertently disable pthread asynchronous cancellation,
>     set*id synchronization or posix timers.
> 
>   - It might also to security issues if SIGSETXID is masked and set*id
>     functions are called (some threads might have effective user or group
>     id different from the rest).
> 
> The changes are basically:
> 
>   - Change __is_internal_signal to bool and used on all signal function
>     that has a signal number as input.  Also for signal function which accepts
>     signals sets (sigset_t) it assumes that canonical function were used to
>     add/remove signals which lead to some input simplification.
> 
>   - Fix tst-sigset.c to avoid check for SIGCANCEL/SIGTIMER and SIGSETXID.
>     It is rewritten to check each signal indidually and to check realtime
>     signals using canonical macros.
> 
>   - Add generic __clear_internal_signals and __is_internal_signal
>     version since both symbols are used on generic implementations.
> 
>   - Remove superflous sysdeps/nptl/sigfillset.c.
> 
>   - Remove superflous SIGTIMER handling on Linux __is_internal_signal
>     since it is the same of SIGCANCEL.
> 
>   - Remove dangling define and obvious comment on nptl/sigaction.c.
> 
> Checked on x86_64-linux-gnu.
> 
> 	[BZ #22391]
> 	* nptl/sigaction.c (__sigaction): Use __is_internal_signal to
> 	check for internal nptl signals.
> 	* signal/sigaddset.c (sigaddset): Likewise.
> 	* signal/sigdelset.c (sigdelset): Likewise.
> 	* sysdeps/posix/signal.c (__bsd_signal): Likewise.
> 	* sysdeps/posix/sigset.c (sigset): Call and check sigaddset return
> 	value.
> 	* signal/sigfillset.c (sigfillset): User __clear_internal_signals
> 	to filter out internal nptl signals.
> 	* signal/tst-sigset.c (do_test): Check ech signal indidually and
> 	also check realtime signals using standard macros.
> 	* sysdeps/nptl/nptl-signals.h (__clear_internal_signals,
> 	__is_internal_signal): New functions.
> 	* sysdeps/nptl/sigfillset.c: Remove file.
> 	* sysdeps/unix/sysv/linux/nptl-signals.h (__is_internal_signal):
> 	Change return to bool.
> 	(__clear_internal_signals): Remove SIGTIMER clean since it is
> 	equal to SIGCANEL on Linux.
> 	* sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Assume
> 	signal set was constructed using standard functions.
> 	* sysdeps/unix/sysv/linux/sigwait.c (do_sigtwait): Likewise.
> 
> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> Reported-by: Yury Norov <ynorov@caviumnetworks.com>
> ---
>  ChangeLog                                  | 23 ++++++++
>  nptl/sigaction.c                           | 14 +----
>  signal/sigaction.c                         |  2 +-
>  signal/sigaddset.c                         |  5 +-
>  signal/sigdelset.c                         |  5 +-
>  signal/sigfillset.c                        | 10 +---
>  signal/tst-sigset.c                        | 92 ++++++++++++++++++++++--------
>  sysdeps/generic/internal-signals.h         | 11 ++++
>  sysdeps/nptl/sigfillset.c                  | 20 -------
>  sysdeps/posix/signal.c                     |  5 +-
>  sysdeps/posix/sigset.c                     | 10 +---
>  sysdeps/unix/sysv/linux/internal-signals.h |  4 +-
>  sysdeps/unix/sysv/linux/sigtimedwait.c     | 17 +-----
>  13 files changed, 122 insertions(+), 96 deletions(-)
>  delete mode 100644 sysdeps/nptl/sigfillset.c
> 
> diff --git a/nptl/sigaction.c b/nptl/sigaction.c
> index ddf6f5e..79b6fdc 100644
> --- a/nptl/sigaction.c
> +++ b/nptl/sigaction.c
> @@ -16,22 +16,12 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -
> -/* This is no complete implementation.  The file is meant to be
> -   included in the real implementation to provide the wrapper around
> -   __libc_sigaction.  */
> -
> -#include <nptl/pthreadP.h>
> -
> -/* We use the libc implementation but we tell it to not allow
> -   SIGCANCEL or SIGTIMER to be handled.  */
> -#define LIBC_SIGACTION	1
> -
> +#include <internal-signals.h>
>  
>  int
>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>  {
> -  if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>      {
>        __set_errno (EINVAL);
>        return -1;
> diff --git a/signal/sigaction.c b/signal/sigaction.c
> index f761ca2..c99001a 100644
> --- a/signal/sigaction.c
> +++ b/signal/sigaction.c
> @@ -24,7 +24,7 @@
>  int
>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>  {
> -  if (sig <= 0 || sig >= NSIG)
> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>      {
>        __set_errno (EINVAL);
>        return -1;
> diff --git a/signal/sigaddset.c b/signal/sigaddset.c
> index d310890..7238df4 100644
> --- a/signal/sigaddset.c
> +++ b/signal/sigaddset.c
> @@ -17,13 +17,14 @@
>  
>  #include <errno.h>
>  #include <signal.h>
> -#include <sigsetops.h>
> +#include <internal-signals.h>
>  
>  /* Add SIGNO to SET.  */
>  int
>  sigaddset (sigset_t *set, int signo)
>  {
> -  if (set == NULL || signo <= 0 || signo >= NSIG)
> +  if (set == NULL || signo <= 0 || signo >= NSIG
> +      || __is_internal_signal (signo))
>      {
>        __set_errno (EINVAL);
>        return -1;
> diff --git a/signal/sigdelset.c b/signal/sigdelset.c
> index cd83dda..011978c 100644
> --- a/signal/sigdelset.c
> +++ b/signal/sigdelset.c
> @@ -17,13 +17,14 @@
>  
>  #include <errno.h>
>  #include <signal.h>
> -#include <sigsetops.h>
> +#include <internal-signals.h>
>  
>  /* Add SIGNO to SET.  */
>  int
>  sigdelset (sigset_t *set, int signo)
>  {
> -  if (set == NULL || signo <= 0 || signo >= NSIG)
> +  if (set == NULL || signo <= 0 || signo >= NSIG
> +      || __is_internal_signal (signo))
>      {
>        __set_errno (EINVAL);
>        return -1;
> diff --git a/signal/sigfillset.c b/signal/sigfillset.c
> index e586fd9..83dd583 100644
> --- a/signal/sigfillset.c
> +++ b/signal/sigfillset.c
> @@ -18,6 +18,7 @@
>  #include <errno.h>
>  #include <signal.h>
>  #include <string.h>
> +#include <internal-signals.h>
>  
>  /* Set all signals in SET.  */
>  int
> @@ -31,14 +32,7 @@ sigfillset (sigset_t *set)
>  
>    memset (set, 0xff, sizeof (sigset_t));
>  
> -  /* If the implementation uses a cancellation signal don't set the bit.  */
> -#ifdef SIGCANCEL
> -  __sigdelset (set, SIGCANCEL);
> -#endif
> -  /* Likewise for the signal to implement setxid.  */
> -#ifdef SIGSETXID
> -  __sigdelset (set, SIGSETXID);
> -#endif
> +  __clear_internal_signals (set);
>  
>    return 0;
>  }
> diff --git a/signal/tst-sigset.c b/signal/tst-sigset.c
> index d47adcc..a2b764d 100644
> --- a/signal/tst-sigset.c
> +++ b/signal/tst-sigset.c
> @@ -1,43 +1,85 @@
>  /* Test sig*set functions.  */
>  
>  #include <signal.h>
> -#include <stdio.h>
>  
> -#define TEST_FUNCTION do_test ()
> +#include <support/check.h>
> +
>  static int
>  do_test (void)
>  {
> -  int result = 0;
> -  int sig = -1;
> +  sigset_t set;
> +  TEST_VERIFY (sigemptyset (&set) == 0);
>  
> -#define TRY(call)							      \
> -  if (call)								      \
> -    {									      \
> -      printf ("%s (sig = %d): %m\n", #call, sig);			      \
> -      result = 1;							      \
> -    }									      \
> -  else
> +#define VERIFY(set, sig)			\
> +  TEST_VERIFY (sigismember (&set, sig) == 0);	\
> +  TEST_VERIFY (sigaddset (&set, sig) == 0);	\
> +  TEST_VERIFY (sigismember (&set, sig) != 0);	\
> +  TEST_VERIFY (sigdelset (&set, sig) == 0);	\
> +  TEST_VERIFY (sigismember (&set, sig) == 0)
>  
> +  /* ISO C99 signals.  */
> +  VERIFY (set, SIGINT);
> +  VERIFY (set, SIGILL);
> +  VERIFY (set, SIGABRT);
> +  VERIFY (set, SIGFPE);
> +  VERIFY (set, SIGSEGV);
> +  VERIFY (set, SIGTERM);
>  
> -  sigset_t set;
> -  TRY (sigemptyset (&set) != 0);
> +  /* Historical signals specified by POSIX. */
> +  VERIFY (set, SIGHUP);
> +  VERIFY (set, SIGQUIT);
> +  VERIFY (set, SIGTRAP);
> +  VERIFY (set, SIGKILL);
> +  VERIFY (set, SIGBUS);
> +  VERIFY (set, SIGSYS);
> +  VERIFY (set, SIGPIPE);
> +  VERIFY (set, SIGALRM);
> +
> +  /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
> +  VERIFY (set, SIGURG);
> +  VERIFY (set, SIGSTOP);
> +  VERIFY (set, SIGTSTP);
> +  VERIFY (set, SIGCONT);
> +  VERIFY (set, SIGCHLD);
> +  VERIFY (set, SIGTTIN);
> +  VERIFY (set, SIGTTOU);
> +  VERIFY (set, SIGPOLL);
> +  VERIFY (set, SIGXCPU);
> +  VERIFY (set, SIGXFSZ);
> +  VERIFY (set, SIGVTALRM);
> +  VERIFY (set, SIGPROF);
> +  VERIFY (set, SIGUSR1);
> +  VERIFY (set, SIGUSR2);
> +
> +  /* Nonstandard signals found in all modern POSIX systems
> +     (including both BSD and Linux).  */
> +  VERIFY (set, SIGWINCH);
>  
> -#ifdef SIGRTMAX
> -  int max_sig = SIGRTMAX;
> -#else
> -  int max_sig = NSIG - 1;
> +  /* Arch-specific signals.  */
> +#ifdef SIGEMT
> +  VERIFY (set, SIGEMT);
> +#endif
> +#ifdef SIGLOST
> +  VERIFY (set, SIGLOST);
> +#endif
> +#ifdef SIGINFO
> +  VERIFY (set, SIGINFO);
> +#endif
> +#ifdef SIGSTKFLT
> +  VERIFY (set, SIGSTKFLT);
> +#endif
> +#ifdef SIGPWR
> +  VERIFY (set, SIGPWR);
>  #endif
>  
> -  for (sig = 1; sig <= max_sig; ++sig)
> +  /* Read-time signals (POSIX.1b real-time extensions).  If they are
> +     supported SIGRTMAX value is greater than SIGRTMIN.  */
> +  for (int rtsig = SIGRTMIN; rtsig <= SIGRTMAX; rtsig++)
>      {
> -      TRY (sigismember (&set, sig) != 0);
> -      TRY (sigaddset (&set, sig) != 0);
> -      TRY (sigismember (&set, sig) == 0);
> -      TRY (sigdelset (&set, sig) != 0);
> -      TRY (sigismember (&set, sig) != 0);
> +      VERIFY (set, rtsig);
>      }
>  
> -  return result;
> +  return 0;
>  }
>  
> -#include "../test-skeleton.c"
> +#include <support/test-driver.c>
> diff --git a/sysdeps/generic/internal-signals.h b/sysdeps/generic/internal-signals.h
> index 01e5b75..ab0b22e 100644
> --- a/sysdeps/generic/internal-signals.h
> +++ b/sysdeps/generic/internal-signals.h
> @@ -15,3 +15,14 @@
>     You should have received a copy of the GNU Lesser General Public
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
> +
> +static inline void
> +__clear_internal_signals (sigset_t *set)
> +{
> +}
> +
> +static inline bool
> +__is_internal_signal (int sig)
> +{
> +  return false;
> +}
> diff --git a/sysdeps/nptl/sigfillset.c b/sysdeps/nptl/sigfillset.c
> deleted file mode 100644
> index 94a7680..0000000
> --- a/sysdeps/nptl/sigfillset.c
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library; if not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#include <nptl/pthreadP.h>
> -
> -#include <signal/sigfillset.c>
> diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c
> index a4a0875..8a135c7 100644
> --- a/sysdeps/posix/signal.c
> +++ b/sysdeps/posix/signal.c
> @@ -18,8 +18,8 @@
>  
>  #include <errno.h>
>  #include <signal.h>
> -#include <string.h>	/* For the real memset prototype.  */
>  #include <sigsetops.h>
> +#include <internal-signals.h>
>  
>  sigset_t _sigintr attribute_hidden;		/* Set by siginterrupt.  */
>  
> @@ -31,7 +31,8 @@ __bsd_signal (int sig, __sighandler_t handler)
>    struct sigaction act, oact;
>  
>    /* Check signal extents to protect __sigismember.  */
> -  if (handler == SIG_ERR || sig < 1 || sig >= NSIG)
> +  if (handler == SIG_ERR || sig < 1 || sig >= NSIG
> +      || __is_internal_signal (sig))
>      {
>        __set_errno (EINVAL);
>        return SIG_ERR;
> diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c
> index b62aa3c..6ab4a48 100644
> --- a/sysdeps/posix/sigset.c
> +++ b/sysdeps/posix/sigset.c
> @@ -31,15 +31,9 @@ sigset (int sig, __sighandler_t disp)
>    sigset_t set;
>    sigset_t oset;
>  
> -  /* Check signal extents to protect __sigismember.  */
> -  if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
> -    {
> -      __set_errno (EINVAL);
> -      return SIG_ERR;
> -    }
> -
>    __sigemptyset (&set);
> -  __sigaddset (&set, sig);
> +  if (sigaddset (&set, sig) < 0)
> +    return SIG_ERR;
>  
>    if (disp == SIG_HOLD)
>      {
> diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
> index e007372..5ff4cf8 100644
> --- a/sysdeps/unix/sysv/linux/internal-signals.h
> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
> @@ -21,6 +21,8 @@
>  
>  #include <signal.h>
>  #include <sigsetops.h>
> +#include <stdbool.h>
> +#include <sysdep.h>
>  
>  /* The signal used for asynchronous cancelation.  */
>  #define SIGCANCEL       __SIGRTMIN
> @@ -37,7 +39,7 @@
>  
>  
>  /* Return is sig is used internally.  */
> -static inline int
> +static inline bool
>  __is_internal_signal (int sig)
>  {
>    return (sig == SIGCANCEL) || (sig == SIGSETXID);
> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
> index 051a285..b4de885 100644
> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
> @@ -24,21 +24,8 @@ int
>  __sigtimedwait (const sigset_t *set, siginfo_t *info,
>  		const struct timespec *timeout)
>  {
> -  sigset_t tmpset;
> -  if (set != NULL
> -      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
> -	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
> -    {
> -      /* Create a temporary mask without the bit for SIGCANCEL set.  */
> -      // We are not copying more than we have to.
> -      memcpy (&tmpset, set, _NSIG / 8);
> -      __sigdelset (&tmpset, SIGCANCEL);
> -      __sigdelset (&tmpset, SIGSETXID);
> -      set = &tmpset;
> -    }
> -
> -    /* XXX The size argument hopefully will have to be changed to the
> -       real size of the user-level sigset_t.  */
> +  /* XXX The size argument hopefully will have to be changed to the
> +     real size of the user-level sigset_t.  */
>    int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
>  
>    /* The kernel generates a SI_TKILL code in si_code in case tkill is
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h
  2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2018-02-12 14:02 ` [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) Adhemerval Zanella
@ 2018-02-19 17:51 ` Adhemerval Zanella
  2018-02-20 13:00 ` Florian Weimer
  4 siblings, 0 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-19 17:51 UTC (permalink / raw)
  To: libc-alpha

Ping.

On 12/02/2018 10:42, Adhemerval Zanella wrote:
> Changes from previous version:
> 
>   - Fixed documentation issues pointed out by Rical Jasan.
> 
> --
> 
> This patch renames the nptl-signals.h header to internal-signals.h.
> On Linux the definitions and functions are not only NPTL related, but
> used for other POSIX definitions as well (for instance SIGTIMER for
> posix times, SIGSETXID for id functions, and signal block/restore
> helpers) and since generic functions will be places and used in generic
> implementation it makes more sense to decouple it from NPTL.
> 
> Checked on x86_64-linux-gnu.
> 
> 	* sysdeps/nptl/nptl-signals.h: Move to ...
> 	* sysdeps/generic/internal-signals.h: ... here.  Adjust internal
> 	comments.
> 	* sysdeps/unix/sysv/linux/internal-signals.h: Add include guards.
> 	(__nptl_is_internal_signal): Rename to __is_internal_signal.
> 	(__nptl_clear_internal_signals): Rename to __clear_internal_signals.
> 	* sysdeps/unix/sysv/linux/raise.c: Adjust nptl-signal.h to
> 	include-signals.h rename.
> 	* nptl/pthreadP.h: Likewise.
> 	* sysdeps/unix/sysv/linux/spawni.c (__spawni_child): Call
> 	__is_internal_signal instead of __nptl_is_internal_signal.
> 
> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
>  ChangeLog                                                | 14 ++++++++++++++
>  nptl/pthreadP.h                                          |  2 +-
>  .../{nptl/nptl-signals.h => generic/internal-signals.h}  |  7 +------
>  .../sysv/linux/{nptl-signals.h => internal-signals.h}    | 16 ++++++++++------
>  sysdeps/unix/sysv/linux/raise.c                          |  2 +-
>  sysdeps/unix/sysv/linux/spawni.c                         |  2 +-
>  6 files changed, 28 insertions(+), 15 deletions(-)
>  rename sysdeps/{nptl/nptl-signals.h => generic/internal-signals.h} (74%)
>  rename sysdeps/unix/sysv/linux/{nptl-signals.h => internal-signals.h} (89%)
> 
> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> index 583515f..075530c 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -32,7 +32,7 @@
>  #include <atomic.h>
>  #include <kernel-features.h>
>  #include <errno.h>
> -#include <nptl-signals.h>
> +#include <internal-signals.h>
>  
>  
>  /* Atomic operations on TLS memory.  */
> diff --git a/sysdeps/nptl/nptl-signals.h b/sysdeps/generic/internal-signals.h
> similarity index 74%
> rename from sysdeps/nptl/nptl-signals.h
> rename to sysdeps/generic/internal-signals.h
> index e1275c7..01e5b75 100644
> --- a/sysdeps/nptl/nptl-signals.h
> +++ b/sysdeps/generic/internal-signals.h
> @@ -1,4 +1,4 @@
> -/* Special use of signals in NPTL internals.  Stub version.
> +/* Special use of signals internally.  Stub version.
>     Copyright (C) 2014-2018 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>  
> @@ -15,8 +15,3 @@
>     You should have received a copy of the GNU Lesser General Public
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
> -
> -/* This file can define the macros SIGCANCEL, SIGTIMER, and SIGSETXID to
> -   signal numbers reserved by libpthread for those internal purposes.
> -
> -   Note that some code presumes SIGTIMER is the same as SIGCANCEL.  */
> diff --git a/sysdeps/unix/sysv/linux/nptl-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
> similarity index 89%
> rename from sysdeps/unix/sysv/linux/nptl-signals.h
> rename to sysdeps/unix/sysv/linux/internal-signals.h
> index e789198..e007372 100644
> --- a/sysdeps/unix/sysv/linux/nptl-signals.h
> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
> @@ -1,4 +1,4 @@
> -/* Special use of signals in NPTL internals.  Linux version.
> +/* Special use of signals internally.  Linux version.
>     Copyright (C) 2014-2018 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>  
> @@ -16,6 +16,9 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#ifndef __INTERNAL_SIGNALS_H
> +# define __INTERNAL_SIGNALS_H
> +
>  #include <signal.h>
>  #include <sigsetops.h>
>  
> @@ -35,17 +38,16 @@
>  
>  /* Return is sig is used internally.  */
>  static inline int
> -__nptl_is_internal_signal (int sig)
> +__is_internal_signal (int sig)
>  {
> -  return (sig == SIGCANCEL) || (sig == SIGTIMER) || (sig == SIGSETXID);
> +  return (sig == SIGCANCEL) || (sig == SIGSETXID);
>  }
>  
>  /* Remove internal glibc signal from the mask.  */
>  static inline void
> -__nptl_clear_internal_signals (sigset_t *set)
> +__clear_internal_signals (sigset_t *set)
>  {
>    __sigdelset (set, SIGCANCEL);
> -  __sigdelset (set, SIGTIMER);
>    __sigdelset (set, SIGSETXID);
>  }
>  
> @@ -66,7 +68,7 @@ static inline int
>  __libc_signal_block_app (sigset_t *set)
>  {
>    sigset_t allset = SIGALL_SET;
> -  __nptl_clear_internal_signals (&allset);
> +  __clear_internal_signals (&allset);
>    INTERNAL_SYSCALL_DECL (err);
>    return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set,
>  			   _NSIG / 8);
> @@ -83,3 +85,5 @@ __libc_signal_restore_set (const sigset_t *set)
>  
>  /* Used to communicate with signal handler.  */
>  extern struct xid_command *__xidcmd attribute_hidden;
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c
> index cb98f90..b05eae2 100644
> --- a/sysdeps/unix/sysv/linux/raise.c
> +++ b/sysdeps/unix/sysv/linux/raise.c
> @@ -21,7 +21,7 @@
>  #include <errno.h>
>  #include <sys/types.h>
>  #include <unistd.h>
> -#include <nptl-signals.h>
> +#include <internal-signals.h>
>  
>  int
>  raise (int sig)
> diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
> index 6b699a4..0391b9b 100644
> --- a/sysdeps/unix/sysv/linux/spawni.c
> +++ b/sysdeps/unix/sysv/linux/spawni.c
> @@ -144,7 +144,7 @@ __spawni_child (void *arguments)
>  	}
>        else if (sigismember (&hset, sig))
>  	{
> -	  if (__nptl_is_internal_signal (sig))
> +	  if (__is_internal_signal (sig))
>  	    sa.sa_handler = SIG_IGN;
>  	  else
>  	    {
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 3/4] linux: Consolidate sigaction implementation
  2018-02-12 12:53 ` [PATCH v4 3/4] linux: Consolidate sigaction implementation Adhemerval Zanella
@ 2018-02-19 17:54   ` Adhemerval Zanella
  2018-04-05 18:23     ` Adhemerval Zanella
  0 siblings, 1 reply; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-19 17:54 UTC (permalink / raw)
  To: libc-alpha

Ping.

On 12/02/2018 10:42, Adhemerval Zanella wrote:
> This patch consolidates all Linux sigaction implementation on a default
> one at sysdeps/unix/sysv/linux/sigaction.c.  The idea is remove redundant
> code and simplify new ports addition by following the current generic
> Linux User API (UAPI).
> 
> The UAPI for new ports defines a generic extensible sigaction struct as:
> 
>   struct sigaction
>   {
>     __sighandler_t sa_handler;
>     unsigned long sa_flags;
>   #ifdef SA_RESTORER
>     void (*sa_restorer) (void);
>   #endif
>     sigset_t sa_mask;
>   };
> 
> Where SA_RESTORER is just placed to compatibility reasons, news ports
> should not add it.  A similar definition is used on generic
> kernel_sigaction.h.
> 
> The user exported sigaction definition is not changed, so for most
> architectures it requires an adjustment to kernel expected one for the
> syscall.
> 
> The main changes are:
> 
>   - All architectures now define and use a kernel_sigaction struct meant
>     for the syscall, even for the architectures where the user sigaction
>     has the same layout of the kernel expected one (s390-64 and ia64).
>     Although it requires more work for these architectures, it simplifies
>     the generic implementation. Also, sigaction is hardly a hotspot where
>     micro optimization would play an important role.
> 
>   - The generic kernel_sigaction definition is now aligned with expected
>     UAPI one for newer ports, where SA_RESTORER and sa_restorer is not
>     expected to be defined.  This means adding kernel_sigaction for
>     current architectures that does define it (m68k, nios2, powerpc, s390,
>     sh, sparc, and tile) and which rely on previous generic definition.
> 
>   - Remove old MIPS usage of sa_restorer.  This was removed since 2.6.27
>     (2957c9e61ee9c - "[MIPS] IRIX: Goodbye and thanks for all the fish").
> 
> So for new ports the generic implementation should work if its uses
> Linux UAPI.  If SA_RESTORER is still required (due some architecture
> limitation), it should define its own kernel_sigaction.h, define it and
> include generic header (assuming it still uses the default generic kernel
> layout).
> 
> Checked on x86_64-linux-gnu, i686-linux-gnu, arm-linux-gnueabihf,
> aarch64-linux-gnu, sparc64-linux-gnu, sparcv9-linux-gnu, powerpc-linux-gnu,
> and powerpc64-linux-gnu.  I also check the build on all remaining affected
> ABIs.
> 
> 	* sysdeps/unix/sysv/linux/aarch64/sigaction.c: Use default Linux version
> 	as base implementation.
> 	* sysdeps/unix/sysv/linux/arm/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h: Add include guards,
> 	remove unrequired definitions and update comments.
> 	* sysdeps/unix/sysv/linux/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h: New file.
> 	* sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/kernel_sigaction: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/kernel_sigaction.h: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/sigaction.c: Remove file.
> 	* sysdeps/unix/sysv/linux/mips/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c: Likewise.
> 	* sysdeps/unix/sysv/linux/sigaction.c: Add STUB, SET_SA_RESTORER,
> 	and RESET_SA_RESTORER hooks.
> 
> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
>  ChangeLog                                          |  25 +++++
>  sysdeps/unix/sysv/linux/aarch64/sigaction.c        |  58 ++---------
>  sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h   |  21 ++--
>  sysdeps/unix/sysv/linux/arm/sigaction.c            |  79 +++-----------
>  sysdeps/unix/sysv/linux/i386/sigaction.c           |  76 +++-----------
>  sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h    |   6 ++
>  sysdeps/unix/sysv/linux/ia64/sigaction.c           |  45 --------
>  sysdeps/unix/sysv/linux/kernel_sigaction.h         |  31 +++---
>  sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h    |  22 ++++
>  sysdeps/unix/sysv/linux/mips/kernel_sigaction.h    |  48 ++-------
>  sysdeps/unix/sysv/linux/mips/sigaction.c           | 116 ---------------------
>  sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h   |   8 ++
>  sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h |   8 ++
>  sysdeps/unix/sysv/linux/s390/kernel_sigaction.h    |  28 +++++
>  sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c   |  43 --------
>  sysdeps/unix/sysv/linux/sh/kernel_sigaction.h      |   8 ++
>  sysdeps/unix/sysv/linux/sigaction.c                |  28 ++---
>  sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h   |  10 ++
>  sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c  |  41 +-------
>  sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c  |  43 +-------
>  sysdeps/unix/sysv/linux/tile/kernel_sigaction.h    |   9 ++
>  sysdeps/unix/sysv/linux/x86_64/sigaction.c         |  61 ++---------
>  22 files changed, 230 insertions(+), 584 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
>  delete mode 100644 sysdeps/unix/sysv/linux/ia64/sigaction.c
>  create mode 100644 sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
>  delete mode 100644 sysdeps/unix/sysv/linux/mips/sigaction.c
>  create mode 100644 sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
>  create mode 100644 sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
>  create mode 100644 sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
>  create mode 100644 sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
> 
> diff --git a/sysdeps/unix/sysv/linux/aarch64/sigaction.c b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
> index 73f4eb7..83d5b4f 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
> @@ -1,5 +1,4 @@
>  /* Copyright (C) 1997-2018 Free Software Foundation, Inc.
> -
>     This file is part of the GNU C Library.
>  
>     The GNU C Library is free software; you can redistribute it and/or
> @@ -16,55 +15,16 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <errno.h>
> -#include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> +/* Required for AArch32 compatibility. */
>  #define SA_RESTORER	0x04000000
>  
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> -#include <kernel_sigaction.h>
> -
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int result;
> -  struct kernel_sigaction kact;
> -  struct kernel_sigaction koact;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -      kact.sa_flags = act->sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      if (kact.sa_flags & SA_RESTORER)
> -	kact.sa_restorer = act->sa_restorer;
> -#endif
> -    }
> +#define SET_SA_RESTORER(kact, act)				\
> + ({								\
> +    if ((kact)->sa_flags & SA_RESTORER)				\
> +      (kact)->sa_restorer = (act)->sa_restorer;			\
> + })
>  
> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
> -			   act ? &kact : NULL,
> -			   oact ? &koact : NULL, _NSIG / 8);
> -  if (result >= 0 || errno != ENOSYS)
> -    {
> -      if (oact && result >= 0)
> -	{
> -	  oact->sa_handler = koact.k_sa_handler;
> -	  memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -	  oact->sa_flags = koact.sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -	  oact->sa_restorer = koact.sa_restorer;
> -#endif
> -	}
> -    }
> -  return result;
> -}
> -libc_hidden_def (__libc_sigaction)
> +#define RESET_SA_RESTORER(act, kact)				\
> +  (act)->sa_restorer = (kact)->sa_restorer;
>  
> -#include <nptl/sigaction.c>
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
> diff --git a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
> index 4c35d96..25180ff 100644
> --- a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
> +++ b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
> @@ -1,15 +1,12 @@
> -/* This is the sigaction struction from the Linux 2.1.20 kernel.  */
> +#ifndef _KERNEL_SIGACTION_H
> +# define _KERNEL_SIGACTION_H
>  
> -struct old_kernel_sigaction {
> -	__sighandler_t k_sa_handler;
> -	unsigned long sa_mask;
> -	unsigned int sa_flags;
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction
> +{
> +  __sighandler_t k_sa_handler;
> +  unsigned int sa_flags;
> +  sigset_t sa_mask;
>  };
>  
> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
> -
> -struct kernel_sigaction {
> -	__sighandler_t k_sa_handler;
> -	unsigned int sa_flags;
> -	sigset_t sa_mask;
> -};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/arm/sigaction.c b/sysdeps/unix/sysv/linux/arm/sigaction.c
> index e4d80de..c828250 100644
> --- a/sysdeps/unix/sysv/linux/arm/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/arm/sigaction.c
> @@ -15,70 +15,25 @@
>     License along with the GNU C Library.  If not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <errno.h>
> -#include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> -#include <kernel_sigaction.h>
> -
>  #define SA_RESTORER	0x04000000
>  
>  extern void __default_sa_restorer (void);
>  extern void __default_rt_sa_restorer (void);
>  
> -/* When RT signals are in use we need to use a different return stub.  */
> -#define choose_restorer(flags)					\
> -  (flags & SA_SIGINFO) ? __default_rt_sa_restorer		\
> -  : __default_sa_restorer
> -
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int result;
> -
> -  struct kernel_sigaction kact, koact;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -      kact.sa_flags = act->sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      if (kact.sa_flags & SA_RESTORER)
> -	kact.sa_restorer = act->sa_restorer;
> -      else
> -	{
> -	  kact.sa_restorer = choose_restorer (kact.sa_flags);
> -	  kact.sa_flags |= SA_RESTORER;
> -	}
> -#endif
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
> -			   act ? &kact : NULL,
> -			   oact ? &koact : NULL, _NSIG / 8);
> -
> -  if (oact && result >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      oact->sa_restorer = koact.sa_restorer;
> -#endif
> -    }
> -  return result;
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> +#define SET_SA_RESTORER(kact, act)				\
> + ({								\
> +   if ((kact)->sa_flags & SA_RESTORER)				\
> +     (kact)->sa_restorer = (act)->sa_restorer;			\
> +   else								\
> +     {								\
> +       (kact)->sa_restorer = ((kact)->sa_flags & SA_SIGINFO)	\
> +			     ? __default_rt_sa_restorer		\
> +			     : __default_sa_restorer;		\
> +       (kact)->sa_flags |= SA_RESTORER;				\
> +     }								\
> + })
> +
> +#define RESET_SA_RESTORER(act, kact)				\
> +  (act)->sa_restorer = (kact)->sa_restorer;
> +
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
> index a5eb9e0..137c73b 100644
> --- a/sysdeps/unix/sysv/linux/i386/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
> @@ -16,78 +16,28 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <sysdep.h>
> -#include <errno.h>
> -#include <stddef.h>
>  #include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
>  #include <ldsodefs.h>
>  
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> -#include <kernel_sigaction.h>
> -
> -/* We do not globally define the SA_RESTORER flag so do it here.  */
>  #define SA_RESTORER 0x04000000
>  
> -
> -/* Using the hidden attribute here does not change the code but it
> -   helps to avoid warnings.  */
> -#ifdef __NR_rt_sigaction
>  extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
> -#endif
>  extern void restore (void) asm ("__restore") attribute_hidden;
>  
> +#define SET_SA_RESTORER(kact, act)				\
> +  ({								\
> +     if (GLRO(dl_sysinfo_dso) == NULL)				\
> +       {							\
> +	 (kact)->sa_flags |= SA_RESTORER;			\
> +         (kact)->sa_restorer = (((act)->sa_flags & SA_SIGINFO)	\
> +			       ? &restore_rt : &restore);	\
> +       }							\
> +  })
>  
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int result;
> -
> -  struct kernel_sigaction kact, koact;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      kact.sa_flags = act->sa_flags;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -
> -      if (GLRO(dl_sysinfo_dso) == NULL)
> -	{
> -	  kact.sa_flags |= SA_RESTORER;
> -
> -	  kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
> -			      ? &restore_rt : &restore);
> -	}
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  INTERNAL_SYSCALL_DECL (err);
> -  result = INTERNAL_SYSCALL (rt_sigaction, err, 4,
> -			     sig, act ? &kact : NULL,
> -			     oact ? &koact : NULL, _NSIG / 8);
> -  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
> -     return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
> -								       err));
> -  else if (oact && result >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -      oact->sa_restorer = koact.sa_restorer;
> -    }
> -  return result;
> -}
> -libc_hidden_def (__libc_sigaction)
> +#define RESET_SA_RESTORER(act, kact) \
> +  (act)->sa_restorer = (kact)->sa_restorer
>  
> -#include <nptl/sigaction.c>
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>  
>  /* NOTE: Please think twice before making any changes to the bits of
>     code below.  GDB needs some intimate knowledge about it to
> @@ -108,10 +58,8 @@ asm						\
>     "	int  $0x80"				\
>     );
>  
> -#ifdef __NR_rt_sigaction
>  /* The return code for realtime-signals.  */
>  RESTORE (restore_rt, __NR_rt_sigreturn)
> -#endif
>  
>  /* For the boring old signals.  */
>  #undef RESTORE2
> diff --git a/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
> new file mode 100644
> index 0000000..05813db
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
> @@ -0,0 +1,6 @@
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction {
> +        __sighandler_t k_sa_handler;
> +        unsigned long sa_flags;
> +        sigset_t sa_mask;               /* mask last for extensibility */
> +};
> diff --git a/sysdeps/unix/sysv/linux/ia64/sigaction.c b/sysdeps/unix/sysv/linux/ia64/sigaction.c
> deleted file mode 100644
> index e7fb8cd..0000000
> --- a/sysdeps/unix/sysv/linux/ia64/sigaction.c
> +++ /dev/null
> @@ -1,45 +0,0 @@
> -/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -   Linux/IA64 specific sigaction
> -   Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library; if not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -/* Linux/ia64 only has rt signals, thus we do not even want to try falling
> -   back to the old style signals as the default Linux handler does. */
> -
> -#include <errno.h>
> -#include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* The variable is shared between all wrappers around signal handling
> -   functions which have RT equivalents.  This is the definition.  */
> -
> -
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> diff --git a/sysdeps/unix/sysv/linux/kernel_sigaction.h b/sysdeps/unix/sysv/linux/kernel_sigaction.h
> index d005cbc..2dbec08 100644
> --- a/sysdeps/unix/sysv/linux/kernel_sigaction.h
> +++ b/sysdeps/unix/sysv/linux/kernel_sigaction.h
> @@ -1,19 +1,20 @@
> -/* This is the sigaction structure from the Linux 2.1.20 kernel.  */
> +#ifndef _KERNEL_SIGACTION_H
> +# define _KERNEL_SIGACTION_H
>  
> -#define HAVE_SA_RESTORER
> -
> -struct old_kernel_sigaction {
> -	__sighandler_t k_sa_handler;
> -	unsigned long sa_mask;
> -	unsigned long sa_flags;
> -	void (*sa_restorer) (void);
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction
> +{
> +  __sighandler_t k_sa_handler;
> +  unsigned long sa_flags;
> +#ifdef SA_RESTORER
> +  void (*sa_restorer) (void);
> +#endif
> +  sigset_t sa_mask;
>  };
>  
> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
> +#ifndef SA_RESTORER
> +# define SET_SA_RESTORER(kact, act)
> +# define RESET_SA_RESTORER(act, kact)
> +#endif
>  
> -struct kernel_sigaction {
> -	__sighandler_t k_sa_handler;
> -	unsigned long sa_flags;
> -	void (*sa_restorer) (void);
> -	sigset_t sa_mask;
> -};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
> new file mode 100644
> index 0000000..54972fe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
> @@ -0,0 +1,22 @@
> +#ifndef _KERNEL_SIGACTION_H
> +# define _KERNEL_SIGACTION_H
> +
> +#include <signal.h>
> +
> +#define SA_RESTORER 0x04000000
> +
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction
> +{
> +  __sighandler_t k_sa_handler;
> +  sigset_t sa_mask;
> +  unsigned long sa_flags;
> +  void (*sa_restorer) (void);
> +};
> +
> +#define SET_SA_RESTORER(kact, act)			\
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)			\
> +  (act)->sa_restorer = (kact)->sa_restorer
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
> index b6f52cc..beef976 100644
> --- a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
> +++ b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
> @@ -1,40 +1,12 @@
> -/* This is the sigaction structure from the Linux 2.1.24 kernel.  */
> -
> -#include <sgidefs.h>
> -
> -#define HAVE_SA_RESTORER
> -
> -struct old_kernel_sigaction {
> -	unsigned int	sa_flags;
> -	__sighandler_t	k_sa_handler;
> -	unsigned long	sa_mask;
> -	unsigned int    __pad0[3]; /* reserved, keep size constant */
> -
> -	/* Abi says here follows reserved int[2] */
> -	void		(*sa_restorer)(void);
> -#if (_MIPS_SZPTR < 64)
> -	/*
> -	 * For 32 bit code we have to pad struct sigaction to get
> -	 * constant size for the ABI
> -	 */
> -	int		pad1[1]; /* reserved */
> -#endif
> +#ifndef _KERNEL_SIGACTION_H
> +# define _KERNEL_SIGACTION_H
> +
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction
> +{
> +  unsigned int    sa_flags;
> +  __sighandler_t  k_sa_handler;
> +  sigset_t        sa_mask;
>  };
>  
> -
> -#define _KERNEL_NSIG	       128
> -#define _KERNEL_NSIG_BPW       _MIPS_SZLONG
> -#define _KERNEL_NSIG_WORDS     (_KERNEL_NSIG / _KERNEL_NSIG_BPW)
> -
> -typedef struct {
> -	unsigned long sig[_KERNEL_NSIG_WORDS];
> -} kernel_sigset_t;
> -
> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
> -struct kernel_sigaction {
> -	unsigned int	sa_flags;
> -	__sighandler_t	k_sa_handler;
> -	kernel_sigset_t	sa_mask;
> -	void		(*sa_restorer)(void);
> -	int		s_resv[1]; /* reserved */
> -};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/sigaction.c b/sysdeps/unix/sysv/linux/mips/sigaction.c
> deleted file mode 100644
> index 008b688..0000000
> --- a/sysdeps/unix/sysv/linux/mips/sigaction.c
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library.  If not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#include <errno.h>
> -#include <sgidefs.h>
> -#include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -#include <sgidefs.h>
> -
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> -#include <kernel_sigaction.h>
> -
> -#if _MIPS_SIM != _ABIO32
> -
> -# ifdef __NR_rt_sigreturn
> -static void restore_rt (void) asm ("__restore_rt");
> -# endif
> -# ifdef __NR_sigreturn
> -static void restore (void) asm ("__restore");
> -# endif
> -#endif
> -
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int result;
> -
> -  struct kernel_sigaction kact, koact;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kernel_sigset_t));
> -      kact.sa_flags = act->sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -# if _MIPS_SIM == _ABIO32
> -      kact.sa_restorer = act->sa_restorer;
> -# else
> -      kact.sa_restorer = &restore_rt;
> -# endif
> -#endif
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.	*/
> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
> -			   act ? &kact : NULL,
> -			   oact ? &koact : NULL,
> -			   sizeof (kernel_sigset_t));
> -
> -  if (oact && result >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask,
> -	      sizeof (kernel_sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      oact->sa_restorer = koact.sa_restorer;
> -#endif
> -    }
> -  return result;
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> -
> -
> -/* NOTE: Please think twice before making any changes to the bits of
> -   code below.  GDB needs some intimate knowledge about it to
> -   recognize them as signal trampolines, and make backtraces through
> -   signal handlers work right.  Important are both the names
> -   (__restore_rt) and the exact instruction sequence.
> -   If you ever feel the need to make any changes, please notify the
> -   appropriate GDB maintainer.  */
> -
> -#define RESTORE(name, syscall) RESTORE2 (name, syscall)
> -#define RESTORE2(name, syscall) \
> -asm						\
> -  (						\
> -   ".align 4\n"					\
> -   "__" #name ":\n"				\
> -   "	li $2, " #syscall "\n"			\
> -   "	syscall\n"				\
> -   );
> -
> -/* The return code for realtime-signals.  */
> -#if _MIPS_SIM != _ABIO32
> -# ifdef __NR_rt_sigreturn
> -RESTORE (restore_rt, __NR_rt_sigreturn)
> -# endif
> -# ifdef __NR_sigreturn
> -RESTORE (restore, __NR_sigreturn)
> -# endif
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
> new file mode 100644
> index 0000000..4ada322
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
> @@ -0,0 +1,8 @@
> +/* NIOS2 uses the generic Linux UAPI but defines SA_RESTORER.  */
> +#define SA_RESTORER 0x04000000
> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
> new file mode 100644
> index 0000000..c5213f2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
> @@ -0,0 +1,8 @@
> +/* powerpc kernel sigaction is similar to generic Linux UAPI one.  */
> +#define SA_RESTORER 0x04000000
> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
> new file mode 100644
> index 0000000..a8beaf7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
> @@ -0,0 +1,28 @@
> +#include <bits/types/siginfo_t.h>
> +
> +#define SA_RESTORER	0x04000000
> +
> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
> +struct kernel_sigaction
> +{
> +  union
> +  {
> +    __sighandler_t _sa_handler;
> +    void (*_sa_sigaction)(int, siginfo_t *, void *);
> +  } _u;
> +#define k_sa_handler _u._sa_handler
> +#ifndef __s390x__
> +  sigset_t sa_mask;
> +  unsigned long sa_flags;
> +  void (*sa_restorer)(void);
> +#else
> +  unsigned long sa_flags;
> +  void (*sa_restorer)(void);
> +  sigset_t sa_mask;
> +#endif
> +};
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c b/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
> deleted file mode 100644
> index c13927c..0000000
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library; if not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -/* 64 bit Linux for S/390 only has rt signals, thus we do not even want to try
> -   falling back to the old style signals as the default Linux handler does. */
> -
> -#include <errno.h>
> -#include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* The variable is shared between all wrappers around signal handling
> -   functions which have RT equivalents.  This is the definition.  */
> -
> -
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> diff --git a/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
> new file mode 100644
> index 0000000..7ebcd08
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
> @@ -0,0 +1,8 @@
> +/* SH uses the generic Linux UAPI but defines SA_RESTORER.  */
> +#define SA_RESTORER 0x04000000
> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c
> index 40a311a..0e6851a 100644
> --- a/sysdeps/unix/sysv/linux/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/sigaction.c
> @@ -22,11 +22,19 @@
>  #include <sysdep.h>
>  #include <sys/syscall.h>
>  
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> +/* New ports should not define the obsolete SA_RESTORER, however some
> +   architecture requires for compat mode and/or due old ABI.  */
>  #include <kernel_sigaction.h>
>  
> +#ifndef SA_RESTORER
> +# define SET_SA_RESTORER(kact, act)
> +# define RESET_SA_RESTORER(act, kact)
> +#endif
> +
> +/* SPARC passes the restore function as an argument to rt_sigaction.  */
> +#ifndef STUB
> +# define STUB(act)
> +#endif
>  
>  /* If ACT is not NULL, change the action for SIG to *ACT.
>     If OACT is not NULL, put the old action for SIG in *OACT.  */
> @@ -42,25 +50,21 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>        kact.k_sa_handler = act->sa_handler;
>        memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>        kact.sa_flags = act->sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      kact.sa_restorer = act->sa_restorer;
> -#endif
> +      SET_SA_RESTORER (&kact, act);
>      }
>  
>    /* XXX The size argument hopefully will have to be changed to the
>       real size of the user-level sigset_t.  */
> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
> -			   act ? &kact : NULL,
> -			   oact ? &koact : NULL, _NSIG / 8);
> +  result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
> +				act ? &kact : NULL,
> +				oact ? &koact : NULL, STUB(act) _NSIG / 8);
>  
>    if (oact && result >= 0)
>      {
>        oact->sa_handler = koact.k_sa_handler;
>        memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>        oact->sa_flags = koact.sa_flags;
> -#ifdef HAVE_SA_RESTORER
> -      oact->sa_restorer = koact.sa_restorer;
> -#endif
> +      RESET_SA_RESTORER (oact, &koact);
>      }
>    return result;
>  }
> diff --git a/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
> new file mode 100644
> index 0000000..bee7e9c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
> @@ -0,0 +1,10 @@
> +/* SPARC 'struct __new_sigaction' is similar to generic Linux UAPI with
> +   a sa_restorer field, even though function is passed as an argument
> +   to rt_sigaction syscall.  */
> +#define SA_RESTORER 0x04000000
> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = NULL
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
> index 204a5d8..c1d8f45 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
> @@ -27,43 +27,12 @@
>  static void __rt_sigreturn_stub (void);
>  static void __sigreturn_stub (void);
>  
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  struct kernel_sigaction kact, koact;
> -  unsigned long stub = 0;
> -  int ret;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -      if (((kact.sa_flags = act->sa_flags) & SA_SIGINFO) != 0)
> -	stub = (unsigned long) &__rt_sigreturn_stub;
> -      else
> -	stub = (unsigned long) &__sigreturn_stub;
> -      stub -= 8;
> -      kact.sa_restorer = NULL;
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  ret = INLINE_SYSCALL (rt_sigaction, 5, sig, act ? &kact : 0,
> -			oact ? &koact : 0, stub, _NSIG / 8);
> -
> -  if (oact && ret >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -      oact->sa_restorer = koact.sa_restorer;
> -    }
> -  return ret;
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> +#define STUB(act) \
> +  ((unsigned long)((act->sa_flags & SA_SIGINFO)		\
> +		    ? &__rt_sigreturn_stub		\
> +		    : &__sigreturn_stub) - 8),
>  
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>  
>  static
>  inhibit_stack_protector
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
> index 73cda4c..cfbbc6e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
> @@ -21,50 +21,13 @@
>  #include <string.h>
>  #include <syscall.h>
>  #include <sysdep.h>
> -#include <sys/signal.h>
> -#include <errno.h>
> -
> -#include <kernel_sigaction.h>
> -
> -/* SPARC 64bit userland requires a kernel that has rt signals anyway. */
>  
>  static void __rt_sigreturn_stub (void);
>  
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int ret;
> -  struct kernel_sigaction kact, koact;
> -  unsigned long stub = ((unsigned long) &__rt_sigreturn_stub) - 8;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -      kact.sa_flags = act->sa_flags;
> -      kact.sa_restorer = NULL;
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  ret = INLINE_SYSCALL (rt_sigaction, 5, sig,
> -			act ? &kact : 0,
> -			oact ? &koact : 0, stub, _NSIG / 8);
> -
> -  if (oact && ret >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -      oact->sa_restorer = koact.sa_restorer;
> -    }
> -
> -  return ret;
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> +#define STUB(act) \
> +  (((unsigned long) &__rt_sigreturn_stub) - 8),
>  
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>  
>  static
>  inhibit_stack_protector
> diff --git a/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
> new file mode 100644
> index 0000000..a943d52
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
> @@ -0,0 +1,9 @@
> +/* tile kernel sigaction is similar to generic Linux UAPI one
> +   and SA_RESTORER is used only for binary compatibility.  */
> +#define SA_RESTORER 0x04000000
> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
> +
> +#define SET_SA_RESTORER(kact, act)             \
> +  (kact)->sa_restorer = (act)->sa_restorer
> +#define RESET_SA_RESTORER(act, kact)           \
> +  (act)->sa_restorer = (kact)->sa_restorer
> diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
> index 2f7459f..4e6d9cc 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
> @@ -16,65 +16,20 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <sysdep.h>
> -#include <errno.h>
> -#include <stddef.h>
>  #include <signal.h>
> -#include <string.h>
> -
> -#include <sysdep.h>
> -#include <sys/syscall.h>
> -
> -/* The difference here is that the sigaction structure used in the
> -   kernel is not the same as we use in the libc.  Therefore we must
> -   translate it here.  */
> -#include <kernel_sigaction.h>
> -
> -#include "ucontext_i.h"
> -
> -/* We do not globally define the SA_RESTORER flag so do it here.  */
>  #define SA_RESTORER 0x04000000
> +#include <kernel_sigaction.h>
>  
> -/* Using the hidden attribute here does not change the code but it
> -   helps to avoid warnings.  */
>  extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
>  
> +#define SET_SA_RESTORER(kact, act)			\
> +  (kact)->sa_flags = (act)->sa_flags | SA_RESTORER;	\
> +  (kact)->sa_restorer = &restore_rt
>  
> -/* If ACT is not NULL, change the action for SIG to *ACT.
> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
> -int
> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
> -{
> -  int result;
> -  struct kernel_sigaction kact, koact;
> -
> -  if (act)
> -    {
> -      kact.k_sa_handler = act->sa_handler;
> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
> -      kact.sa_flags = act->sa_flags | SA_RESTORER;
> -
> -      kact.sa_restorer = &restore_rt;
> -    }
> -
> -  /* XXX The size argument hopefully will have to be changed to the
> -     real size of the user-level sigset_t.  */
> -  result = INLINE_SYSCALL (rt_sigaction, 4,
> -			   sig, act ? &kact : NULL,
> -			   oact ? &koact : NULL, _NSIG / 8);
> -  if (oact && result >= 0)
> -    {
> -      oact->sa_handler = koact.k_sa_handler;
> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
> -      oact->sa_flags = koact.sa_flags;
> -      oact->sa_restorer = koact.sa_restorer;
> -    }
> -  return result;
> -}
> -libc_hidden_def (__libc_sigaction)
> -
> -#include <nptl/sigaction.c>
> +#define RESET_SA_RESTORER(act, kact) 			\
> +  (act)->sa_restorer = (kact)->sa_restorer
>  
> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>  
>  /* NOTE: Please think twice before making any changes to the bits of
>     code below.  GDB needs some intimate knowledge about it to
> @@ -93,6 +48,8 @@ libc_hidden_def (__libc_sigaction)
>     a bit tricky.  We don't use the gas cfi directives, so that we can
>     reliably add .cfi_signal_frame.  */
>  
> +#include "ucontext_i.h"
> +
>  #define do_cfa_expr						\
>    "	.byte 0x0f\n"		/* DW_CFA_def_cfa_expression */	\
>    "	.uleb128 2f-1f\n"	/* length */			\
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269)
  2018-02-12 14:02 ` [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) Adhemerval Zanella
@ 2018-02-19 18:08   ` Adhemerval Zanella
  2018-02-19 18:23   ` H.J. Lu
  1 sibling, 0 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-19 18:08 UTC (permalink / raw)
  To: libc-alpha

Ping.

On 12/02/2018 10:42, Adhemerval Zanella wrote:
> This patch fixes the i386 sa_restorer field initialization for sigaction
> syscall for kernel with vDSO.  As described in bug report, x86_32 Linux
> (and compat on x86_64) interprets SA_RESTORER clear with nonzero
> sa_restorer as a request for stack switching if the SS segment is 'funny'
> This means that anything that tries to mix glibc's signal handling with
> segmentation (for instance through modify_ldt syscall) is randomly broken
> depending on what values lands in sa_restorer.
> 
> The testcase added  is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
> more specifically in do_multicpu_tests function.  The main changes are:
> 
>   - C11 atomics instead of plain access.
> 
>   - Remove x86_64 support which simplifies the syscall handling and fallbacks.
> 
>   - Replicate only the test required to trigger the issue.
> 
> (I added some comments of my understanding of how the testcase is triggering
> the issue, so if someone with more x86 knowledge could check if I get this
> right I will be grateful)
> 
> Checked on i686-linux-gnu.
> 
> 	[BZ #21269]
> 	* sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269.
> 	* sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear
> 	sa_restorer for vDSO case.
> 	* sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file.
> 
> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
>  ChangeLog                                  |   6 +
>  sysdeps/unix/sysv/linux/i386/Makefile      |   3 +
>  sysdeps/unix/sysv/linux/i386/sigaction.c   |   2 +
>  sysdeps/unix/sysv/linux/i386/tst-bz21269.c | 233 +++++++++++++++++++++++++++++
>  4 files changed, 244 insertions(+)
>  create mode 100644 sysdeps/unix/sysv/linux/i386/tst-bz21269.c
> 
> diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
> index 4080b8c..da716e2 100644
> --- a/sysdeps/unix/sysv/linux/i386/Makefile
> +++ b/sysdeps/unix/sysv/linux/i386/Makefile
> @@ -3,6 +3,9 @@ default-abi := 32
>  
>  ifeq ($(subdir),misc)
>  sysdep_routines += ioperm iopl vm86
> +
> +tests += tst-bz21269
> +$(objpfx)tst-bz21269: $(shared-thread-library)
>  endif
>  
>  ifeq ($(subdir),elf)
> diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
> index 137c73b..df9fa0c 100644
> --- a/sysdeps/unix/sysv/linux/i386/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
> @@ -32,6 +32,8 @@ extern void restore (void) asm ("__restore") attribute_hidden;
>           (kact)->sa_restorer = (((act)->sa_flags & SA_SIGINFO)	\
>  			       ? &restore_rt : &restore);	\
>         }							\
> +     else							\
> +       (kact)->sa_restorer = NULL;				\
>    })
>  
>  #define RESET_SA_RESTORER(act, kact) \
> diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
> new file mode 100644
> index 0000000..353e365
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
> @@ -0,0 +1,233 @@
> +/* Test for i386 sigaction sa_restorer handling (BZ#21269)
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
> +   more specifically in do_multicpu_tests function.  The main changes
> +   are:
> +
> +   - C11 atomics instead of plain access.
> +   - Remove x86_64 support which simplifies the syscall handling
> +     and fallbacks.
> +   - Replicate only the test required to trigger the issue for the
> +     BZ#21269.  */
> +
> +#include <stdatomic.h>
> +
> +#include <asm/ldt.h>
> +#include <linux/futex.h>
> +
> +#include <setjmp.h>
> +#include <signal.h>
> +#include <errno.h>
> +#include <sys/syscall.h>
> +#include <sys/mman.h>
> +
> +#include <support/xunistd.h>
> +#include <support/check.h>
> +#include <support/xthread.h>
> +
> +static int
> +xset_thread_area (struct user_desc *u_info)
> +{
> +  long ret = syscall (SYS_set_thread_area, u_info);
> +  TEST_VERIFY_EXIT (ret == 0);
> +  return ret;
> +}
> +
> +static void
> +xmodify_ldt (int func, const void *ptr, unsigned long bytecount)
> +{
> +  TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0);
> +}
> +
> +static int
> +futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2,
> +	int val3)
> +{
> +  return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
> +}
> +
> +static void
> +xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags)
> +{
> +  struct sigaction sa = { 0 };
> +  sa.sa_sigaction = handler;
> +  sa.sa_flags = SA_SIGINFO | flags;
> +  TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0);
> +  TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0);
> +}
> +
> +static jmp_buf jmpbuf;
> +
> +static void
> +sigsegv_handler (int sig, siginfo_t *info, void *ctx_void)
> +{
> +  siglongjmp (jmpbuf, 1);
> +}
> +
> +/* Points to an array of 1024 ints, each holding its own index.  */
> +static const unsigned int *counter_page;
> +static struct user_desc *low_user_desc;
> +static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry.  */
> +static int gdt_entry_num;
> +
> +static void
> +setup_counter_page (void)
> +{
> +  long page_size = sysconf (_SC_PAGE_SIZE);
> +  TEST_VERIFY_EXIT (page_size > 0);
> +  unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE,
> +			      MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
> +  for (int i = 0; i < (page_size / sizeof (unsigned int)); i++)
> +    page[i] = i;
> +  counter_page = page;
> +}
> +
> +static void
> +setup_low_user_desc (void)
> +{
> +  low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc),
> +			 PROT_READ | PROT_WRITE,
> +			 MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
> +
> +  low_user_desc->entry_number    = -1;
> +  low_user_desc->base_addr       = (unsigned long) &counter_page[1];
> +  low_user_desc->limit           = 0xffff;
> +  low_user_desc->seg_32bit       = 1;
> +  low_user_desc->contents        = 0;
> +  low_user_desc->read_exec_only  = 0;
> +  low_user_desc->limit_in_pages  = 1;
> +  low_user_desc->seg_not_present = 0;
> +  low_user_desc->useable         = 0;
> +
> +  xset_thread_area (low_user_desc);
> +
> +  low_user_desc_clear = low_user_desc + 1;
> +  low_user_desc_clear->entry_number = gdt_entry_num;
> +  low_user_desc_clear->read_exec_only = 1;
> +  low_user_desc_clear->seg_not_present = 1;
> +}
> +
> +/* Possible values of futex:
> +   0: thread is idle.
> +   1: thread armed.
> +   2: thread should clear LDT entry 0.
> +   3: thread should exit.  */
> +static atomic_uint ftx;
> +
> +static void *
> +threadproc (void *ctx)
> +{
> +  while (1)
> +    {
> +      futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
> +      while (atomic_load (&ftx) != 2)
> +	{
> +	  if (atomic_load (&ftx) >= 3)
> +	    return NULL;
> +	}
> +
> +      /* clear LDT entry 0.  */
> +      const struct user_desc desc = { 0 };
> +      xmodify_ldt (1, &desc, sizeof (desc));
> +
> +      /* If ftx == 2, set it to zero,  If ftx == 100, quit.  */
> +      if (atomic_fetch_add (&ftx, -2) != 2)
> +	return NULL;
> +    }
> +}
> +
> +
> +/* As described in testcase, for historical reasons x86_32 Linux (and compat
> +   on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a
> +   request for stack switching if the SS segment is 'funny' (this is default
> +   scenario for vDSO system).  This means that anything that tries to mix
> +   signal handling with segmentation should explicit clear the sa_restorer.
> +
> +   This testcase check if sigaction in fact does it by changing the local
> +   descriptor table (LDT) through the modify_ldt syscall and triggering
> +   a synchronous segfault on iret fault by trying to install an invalid
> +   segment.  With a correct zeroed sa_restorer it should not trigger an
> +   'real' SEGSEGV and allows the siglongjmp in signal handler.  */
> +
> +static int
> +do_test (void)
> +{
> +  setup_counter_page ();
> +  setup_low_user_desc ();
> +
> +  pthread_t thread;
> +  unsigned short orig_ss;
> +
> +  xsethandler (SIGSEGV, sigsegv_handler, 0);
> +  /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults.  */
> +  xsethandler (SIGILL, sigsegv_handler, 0);
> +
> +  thread = xpthread_create (0, threadproc, 0);
> +
> +  asm volatile ("mov %%ss, %0" : "=rm" (orig_ss));
> +
> +  for (int i = 0; i < 5; i++)
> +    {
> +      if (sigsetjmp (jmpbuf, 1) != 0)
> +	continue;
> +
> +      /* Make sure the thread is ready after the last test. */
> +      while (atomic_load (&ftx) != 0)
> +	;
> +
> +      struct user_desc desc = {
> +	.entry_number       = 0,
> +	.base_addr          = 0,
> +	.limit              = 0xffff,
> +	.seg_32bit          = 1,
> +	.contents           = 0,
> +	.read_exec_only     = 0,
> +	.limit_in_pages     = 1,
> +	.seg_not_present    = 0,
> +	.useable            = 0
> +      };
> +
> +      xmodify_ldt (0x11, &desc, sizeof (desc));
> +
> +      /* Arm the thread.  */
> +      ftx = 1;
> +      futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
> +
> +      asm volatile ("mov %0, %%ss" : : "r" (0x7));
> +
> +      /* Fire up thread modify_ldt call.  */
> +      atomic_store (&ftx, 2);
> +
> +      while (atomic_load (&ftx) != 0)
> +	;
> +
> +      /* On success, modify_ldt will segfault us synchronously and we will
> +	 escape via siglongjmp.  */
> +      support_record_failure ();
> +    }
> +
> +  atomic_store (&ftx, 100);
> +  futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
> +
> +  xpthread_join (thread);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269)
  2018-02-12 14:02 ` [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) Adhemerval Zanella
  2018-02-19 18:08   ` Adhemerval Zanella
@ 2018-02-19 18:23   ` H.J. Lu
  1 sibling, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2018-02-19 18:23 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Mon, Feb 12, 2018 at 4:42 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> This patch fixes the i386 sa_restorer field initialization for sigaction
> syscall for kernel with vDSO.  As described in bug report, x86_32 Linux
> (and compat on x86_64) interprets SA_RESTORER clear with nonzero
> sa_restorer as a request for stack switching if the SS segment is 'funny'
> This means that anything that tries to mix glibc's signal handling with
> segmentation (for instance through modify_ldt syscall) is randomly broken
> depending on what values lands in sa_restorer.
>
> The testcase added  is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
> more specifically in do_multicpu_tests function.  The main changes are:
>
>   - C11 atomics instead of plain access.
>
>   - Remove x86_64 support which simplifies the syscall handling and fallbacks.
>
>   - Replicate only the test required to trigger the issue.
>
> (I added some comments of my understanding of how the testcase is triggering
> the issue, so if someone with more x86 knowledge could check if I get this
> right I will be grateful)
>
> Checked on i686-linux-gnu.
>
>         [BZ #21269]
>         * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269.
>         * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear
>         sa_restorer for vDSO case.
>         * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file.
>
> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

LGTM.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h
  2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2018-02-19 17:51 ` [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
@ 2018-02-20 13:00 ` Florian Weimer
  2018-02-20 13:45   ` Adhemerval Zanella
  4 siblings, 1 reply; 15+ messages in thread
From: Florian Weimer @ 2018-02-20 13:00 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

On 02/12/2018 01:42 PM, Adhemerval Zanella wrote:
> This patch renames the nptl-signals.h header to internal-signals.h.
> On Linux the definitions and functions are not only NPTL related, but
> used for other POSIX definitions as well (for instance SIGTIMER for
> posix times, SIGSETXID for id functions, and signal block/restore

POSIX timers?

> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

We don't use DCO, but have copyright assignments.

> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> diff --git a/sysdeps/unix/sysv/linux/nptl-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
> similarity index 89%
> rename from sysdeps/unix/sysv/linux/nptl-signals.h
> rename to sysdeps/unix/sysv/linux/internal-signals.h
> index e789198..e007372 100644
> --- a/sysdeps/unix/sysv/linux/nptl-signals.h
> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
> @@ -1,4 +1,4 @@
> -/* Special use of signals in NPTL internals.  Linux version.
> +/* Special use of signals internally.  Linux version.
>      Copyright (C) 2014-2018 Free Software Foundation, Inc.
>      This file is part of the GNU C Library.
>   
> @@ -16,6 +16,9 @@
>      License along with the GNU C Library; if not, see
>      <http://www.gnu.org/licenses/>.  */
>   
> +#ifndef __INTERNAL_SIGNALS_H
> +# define __INTERNAL_SIGNALS_H
> +
>   #include <signal.h>
>   #include <sigsetops.h>
>   
> @@ -35,17 +38,16 @@
>   
>   /* Return is sig is used internally.  */
>   static inline int
> -__nptl_is_internal_signal (int sig)
> +__is_internal_signal (int sig)
>   {
> -  return (sig == SIGCANCEL) || (sig == SIGTIMER) || (sig == SIGSETXID);
> +  return (sig == SIGCANCEL) || (sig == SIGSETXID);

Should this change be mentioned in the ChangeLog?  You could remove the 
unnecessary parens because you modify this line anyway.

>   /* Remove internal glibc signal from the mask.  */
>   static inline void
> -__nptl_clear_internal_signals (sigset_t *set)
> +__clear_internal_signals (sigset_t *set)
>   {
>     __sigdelset (set, SIGCANCEL);
> -  __sigdelset (set, SIGTIMER);

Likewise, should be mentioned in the ChangeLog entry.

Looks okay otherwise.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h
  2018-02-20 13:00 ` Florian Weimer
@ 2018-02-20 13:45   ` Adhemerval Zanella
  0 siblings, 0 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-02-20 13:45 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 20/02/2018 09:32, Florian Weimer wrote:
> On 02/12/2018 01:42 PM, Adhemerval Zanella wrote:
>> This patch renames the nptl-signals.h header to internal-signals.h.
>> On Linux the definitions and functions are not only NPTL related, but
>> used for other POSIX definitions as well (for instance SIGTIMER for
>> posix times, SIGSETXID for id functions, and signal block/restore
> 
> POSIX timers?
> 
>> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> 
> We don't use DCO, but have copyright assignments.

Right, although I had the impression signed-off-by is mostly optional. I am
trying to find the follow-up thread about it after it was brought up in
Cauldron. Do you know if Carlos has written some wiki entry about it?

> 
>> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
>> diff --git a/sysdeps/unix/sysv/linux/nptl-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
>> similarity index 89%
>> rename from sysdeps/unix/sysv/linux/nptl-signals.h
>> rename to sysdeps/unix/sysv/linux/internal-signals.h
>> index e789198..e007372 100644
>> --- a/sysdeps/unix/sysv/linux/nptl-signals.h
>> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
>> @@ -1,4 +1,4 @@
>> -/* Special use of signals in NPTL internals.  Linux version.
>> +/* Special use of signals internally.  Linux version.
>>      Copyright (C) 2014-2018 Free Software Foundation, Inc.
>>      This file is part of the GNU C Library.
>>   @@ -16,6 +16,9 @@
>>      License along with the GNU C Library; if not, see
>>      <http://www.gnu.org/licenses/>.  */
>>   +#ifndef __INTERNAL_SIGNALS_H
>> +# define __INTERNAL_SIGNALS_H
>> +
>>   #include <signal.h>
>>   #include <sigsetops.h>
>>   @@ -35,17 +38,16 @@
>>     /* Return is sig is used internally.  */
>>   static inline int
>> -__nptl_is_internal_signal (int sig)
>> +__is_internal_signal (int sig)
>>   {
>> -  return (sig == SIGCANCEL) || (sig == SIGTIMER) || (sig == SIGSETXID);
>> +  return (sig == SIGCANCEL) || (sig == SIGSETXID);
> 
> Should this change be mentioned in the ChangeLog?  You could remove the unnecessary parens because you modify this line anyway.

I will add a entry in ChangeLog and remove the unnecessary parentheses. 

> 
>>   /* Remove internal glibc signal from the mask.  */
>>   static inline void
>> -__nptl_clear_internal_signals (sigset_t *set)
>> +__clear_internal_signals (sigset_t *set)
>>   {
>>     __sigdelset (set, SIGCANCEL);
>> -  __sigdelset (set, SIGTIMER);
> 
> Likewise, should be mentioned in the ChangeLog entry.

I will a entry as well.

> 
> Looks okay otherwise.
> 
> Thanks,
> Florian

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391)
  2018-02-19 17:51   ` Adhemerval Zanella
@ 2018-04-03 14:24     ` Adhemerval Zanella
  2018-04-03 15:12       ` Zack Weinberg
  0 siblings, 1 reply; 15+ messages in thread
From: Adhemerval Zanella @ 2018-04-03 14:24 UTC (permalink / raw)
  To: libc-alpha

If no one opposes, I will commit this shortly.

On 19/02/2018 14:50, Adhemerval Zanella wrote:
> Ping.
> 
> On 12/02/2018 10:42, Adhemerval Zanella wrote:
>> This patch filters out the internal NPTL signals (SIGCANCEL/SIGTIMER and
>> SIGSETXID) from signal functions.  GLIBC on Linux requires both signals to
>> proper implement pthread cancellation, posix timers, and set*id posix
>> thread synchronization.
>>
>> And not filtering out the internal signal is troublesome:
>>
>>   - A conformant program on a architecture that does not filter out the
>>     signals might inadvertently disable pthread asynchronous cancellation,
>>     set*id synchronization or posix timers.
>>
>>   - It might also to security issues if SIGSETXID is masked and set*id
>>     functions are called (some threads might have effective user or group
>>     id different from the rest).
>>
>> The changes are basically:
>>
>>   - Change __is_internal_signal to bool and used on all signal function
>>     that has a signal number as input.  Also for signal function which accepts
>>     signals sets (sigset_t) it assumes that canonical function were used to
>>     add/remove signals which lead to some input simplification.
>>
>>   - Fix tst-sigset.c to avoid check for SIGCANCEL/SIGTIMER and SIGSETXID.
>>     It is rewritten to check each signal indidually and to check realtime
>>     signals using canonical macros.
>>
>>   - Add generic __clear_internal_signals and __is_internal_signal
>>     version since both symbols are used on generic implementations.
>>
>>   - Remove superflous sysdeps/nptl/sigfillset.c.
>>
>>   - Remove superflous SIGTIMER handling on Linux __is_internal_signal
>>     since it is the same of SIGCANCEL.
>>
>>   - Remove dangling define and obvious comment on nptl/sigaction.c.
>>
>> Checked on x86_64-linux-gnu.
>>
>> 	[BZ #22391]
>> 	* nptl/sigaction.c (__sigaction): Use __is_internal_signal to
>> 	check for internal nptl signals.
>> 	* signal/sigaddset.c (sigaddset): Likewise.
>> 	* signal/sigdelset.c (sigdelset): Likewise.
>> 	* sysdeps/posix/signal.c (__bsd_signal): Likewise.
>> 	* sysdeps/posix/sigset.c (sigset): Call and check sigaddset return
>> 	value.
>> 	* signal/sigfillset.c (sigfillset): User __clear_internal_signals
>> 	to filter out internal nptl signals.
>> 	* signal/tst-sigset.c (do_test): Check ech signal indidually and
>> 	also check realtime signals using standard macros.
>> 	* sysdeps/nptl/nptl-signals.h (__clear_internal_signals,
>> 	__is_internal_signal): New functions.
>> 	* sysdeps/nptl/sigfillset.c: Remove file.
>> 	* sysdeps/unix/sysv/linux/nptl-signals.h (__is_internal_signal):
>> 	Change return to bool.
>> 	(__clear_internal_signals): Remove SIGTIMER clean since it is
>> 	equal to SIGCANEL on Linux.
>> 	* sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Assume
>> 	signal set was constructed using standard functions.
>> 	* sysdeps/unix/sysv/linux/sigwait.c (do_sigtwait): Likewise.
>>
>> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>> Reported-by: Yury Norov <ynorov@caviumnetworks.com>
>> ---
>>  ChangeLog                                  | 23 ++++++++
>>  nptl/sigaction.c                           | 14 +----
>>  signal/sigaction.c                         |  2 +-
>>  signal/sigaddset.c                         |  5 +-
>>  signal/sigdelset.c                         |  5 +-
>>  signal/sigfillset.c                        | 10 +---
>>  signal/tst-sigset.c                        | 92 ++++++++++++++++++++++--------
>>  sysdeps/generic/internal-signals.h         | 11 ++++
>>  sysdeps/nptl/sigfillset.c                  | 20 -------
>>  sysdeps/posix/signal.c                     |  5 +-
>>  sysdeps/posix/sigset.c                     | 10 +---
>>  sysdeps/unix/sysv/linux/internal-signals.h |  4 +-
>>  sysdeps/unix/sysv/linux/sigtimedwait.c     | 17 +-----
>>  13 files changed, 122 insertions(+), 96 deletions(-)
>>  delete mode 100644 sysdeps/nptl/sigfillset.c
>>
>> diff --git a/nptl/sigaction.c b/nptl/sigaction.c
>> index ddf6f5e..79b6fdc 100644
>> --- a/nptl/sigaction.c
>> +++ b/nptl/sigaction.c
>> @@ -16,22 +16,12 @@
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -
>> -/* This is no complete implementation.  The file is meant to be
>> -   included in the real implementation to provide the wrapper around
>> -   __libc_sigaction.  */
>> -
>> -#include <nptl/pthreadP.h>
>> -
>> -/* We use the libc implementation but we tell it to not allow
>> -   SIGCANCEL or SIGTIMER to be handled.  */
>> -#define LIBC_SIGACTION	1
>> -
>> +#include <internal-signals.h>
>>  
>>  int
>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>  {
>> -  if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>      {
>>        __set_errno (EINVAL);
>>        return -1;
>> diff --git a/signal/sigaction.c b/signal/sigaction.c
>> index f761ca2..c99001a 100644
>> --- a/signal/sigaction.c
>> +++ b/signal/sigaction.c
>> @@ -24,7 +24,7 @@
>>  int
>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>  {
>> -  if (sig <= 0 || sig >= NSIG)
>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>      {
>>        __set_errno (EINVAL);
>>        return -1;
>> diff --git a/signal/sigaddset.c b/signal/sigaddset.c
>> index d310890..7238df4 100644
>> --- a/signal/sigaddset.c
>> +++ b/signal/sigaddset.c
>> @@ -17,13 +17,14 @@
>>  
>>  #include <errno.h>
>>  #include <signal.h>
>> -#include <sigsetops.h>
>> +#include <internal-signals.h>
>>  
>>  /* Add SIGNO to SET.  */
>>  int
>>  sigaddset (sigset_t *set, int signo)
>>  {
>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>> +      || __is_internal_signal (signo))
>>      {
>>        __set_errno (EINVAL);
>>        return -1;
>> diff --git a/signal/sigdelset.c b/signal/sigdelset.c
>> index cd83dda..011978c 100644
>> --- a/signal/sigdelset.c
>> +++ b/signal/sigdelset.c
>> @@ -17,13 +17,14 @@
>>  
>>  #include <errno.h>
>>  #include <signal.h>
>> -#include <sigsetops.h>
>> +#include <internal-signals.h>
>>  
>>  /* Add SIGNO to SET.  */
>>  int
>>  sigdelset (sigset_t *set, int signo)
>>  {
>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>> +      || __is_internal_signal (signo))
>>      {
>>        __set_errno (EINVAL);
>>        return -1;
>> diff --git a/signal/sigfillset.c b/signal/sigfillset.c
>> index e586fd9..83dd583 100644
>> --- a/signal/sigfillset.c
>> +++ b/signal/sigfillset.c
>> @@ -18,6 +18,7 @@
>>  #include <errno.h>
>>  #include <signal.h>
>>  #include <string.h>
>> +#include <internal-signals.h>
>>  
>>  /* Set all signals in SET.  */
>>  int
>> @@ -31,14 +32,7 @@ sigfillset (sigset_t *set)
>>  
>>    memset (set, 0xff, sizeof (sigset_t));
>>  
>> -  /* If the implementation uses a cancellation signal don't set the bit.  */
>> -#ifdef SIGCANCEL
>> -  __sigdelset (set, SIGCANCEL);
>> -#endif
>> -  /* Likewise for the signal to implement setxid.  */
>> -#ifdef SIGSETXID
>> -  __sigdelset (set, SIGSETXID);
>> -#endif
>> +  __clear_internal_signals (set);
>>  
>>    return 0;
>>  }
>> diff --git a/signal/tst-sigset.c b/signal/tst-sigset.c
>> index d47adcc..a2b764d 100644
>> --- a/signal/tst-sigset.c
>> +++ b/signal/tst-sigset.c
>> @@ -1,43 +1,85 @@
>>  /* Test sig*set functions.  */
>>  
>>  #include <signal.h>
>> -#include <stdio.h>
>>  
>> -#define TEST_FUNCTION do_test ()
>> +#include <support/check.h>
>> +
>>  static int
>>  do_test (void)
>>  {
>> -  int result = 0;
>> -  int sig = -1;
>> +  sigset_t set;
>> +  TEST_VERIFY (sigemptyset (&set) == 0);
>>  
>> -#define TRY(call)							      \
>> -  if (call)								      \
>> -    {									      \
>> -      printf ("%s (sig = %d): %m\n", #call, sig);			      \
>> -      result = 1;							      \
>> -    }									      \
>> -  else
>> +#define VERIFY(set, sig)			\
>> +  TEST_VERIFY (sigismember (&set, sig) == 0);	\
>> +  TEST_VERIFY (sigaddset (&set, sig) == 0);	\
>> +  TEST_VERIFY (sigismember (&set, sig) != 0);	\
>> +  TEST_VERIFY (sigdelset (&set, sig) == 0);	\
>> +  TEST_VERIFY (sigismember (&set, sig) == 0)
>>  
>> +  /* ISO C99 signals.  */
>> +  VERIFY (set, SIGINT);
>> +  VERIFY (set, SIGILL);
>> +  VERIFY (set, SIGABRT);
>> +  VERIFY (set, SIGFPE);
>> +  VERIFY (set, SIGSEGV);
>> +  VERIFY (set, SIGTERM);
>>  
>> -  sigset_t set;
>> -  TRY (sigemptyset (&set) != 0);
>> +  /* Historical signals specified by POSIX. */
>> +  VERIFY (set, SIGHUP);
>> +  VERIFY (set, SIGQUIT);
>> +  VERIFY (set, SIGTRAP);
>> +  VERIFY (set, SIGKILL);
>> +  VERIFY (set, SIGBUS);
>> +  VERIFY (set, SIGSYS);
>> +  VERIFY (set, SIGPIPE);
>> +  VERIFY (set, SIGALRM);
>> +
>> +  /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
>> +  VERIFY (set, SIGURG);
>> +  VERIFY (set, SIGSTOP);
>> +  VERIFY (set, SIGTSTP);
>> +  VERIFY (set, SIGCONT);
>> +  VERIFY (set, SIGCHLD);
>> +  VERIFY (set, SIGTTIN);
>> +  VERIFY (set, SIGTTOU);
>> +  VERIFY (set, SIGPOLL);
>> +  VERIFY (set, SIGXCPU);
>> +  VERIFY (set, SIGXFSZ);
>> +  VERIFY (set, SIGVTALRM);
>> +  VERIFY (set, SIGPROF);
>> +  VERIFY (set, SIGUSR1);
>> +  VERIFY (set, SIGUSR2);
>> +
>> +  /* Nonstandard signals found in all modern POSIX systems
>> +     (including both BSD and Linux).  */
>> +  VERIFY (set, SIGWINCH);
>>  
>> -#ifdef SIGRTMAX
>> -  int max_sig = SIGRTMAX;
>> -#else
>> -  int max_sig = NSIG - 1;
>> +  /* Arch-specific signals.  */
>> +#ifdef SIGEMT
>> +  VERIFY (set, SIGEMT);
>> +#endif
>> +#ifdef SIGLOST
>> +  VERIFY (set, SIGLOST);
>> +#endif
>> +#ifdef SIGINFO
>> +  VERIFY (set, SIGINFO);
>> +#endif
>> +#ifdef SIGSTKFLT
>> +  VERIFY (set, SIGSTKFLT);
>> +#endif
>> +#ifdef SIGPWR
>> +  VERIFY (set, SIGPWR);
>>  #endif
>>  
>> -  for (sig = 1; sig <= max_sig; ++sig)
>> +  /* Read-time signals (POSIX.1b real-time extensions).  If they are
>> +     supported SIGRTMAX value is greater than SIGRTMIN.  */
>> +  for (int rtsig = SIGRTMIN; rtsig <= SIGRTMAX; rtsig++)
>>      {
>> -      TRY (sigismember (&set, sig) != 0);
>> -      TRY (sigaddset (&set, sig) != 0);
>> -      TRY (sigismember (&set, sig) == 0);
>> -      TRY (sigdelset (&set, sig) != 0);
>> -      TRY (sigismember (&set, sig) != 0);
>> +      VERIFY (set, rtsig);
>>      }
>>  
>> -  return result;
>> +  return 0;
>>  }
>>  
>> -#include "../test-skeleton.c"
>> +#include <support/test-driver.c>
>> diff --git a/sysdeps/generic/internal-signals.h b/sysdeps/generic/internal-signals.h
>> index 01e5b75..ab0b22e 100644
>> --- a/sysdeps/generic/internal-signals.h
>> +++ b/sysdeps/generic/internal-signals.h
>> @@ -15,3 +15,14 @@
>>     You should have received a copy of the GNU Lesser General Public
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>> +
>> +static inline void
>> +__clear_internal_signals (sigset_t *set)
>> +{
>> +}
>> +
>> +static inline bool
>> +__is_internal_signal (int sig)
>> +{
>> +  return false;
>> +}
>> diff --git a/sysdeps/nptl/sigfillset.c b/sysdeps/nptl/sigfillset.c
>> deleted file mode 100644
>> index 94a7680..0000000
>> --- a/sysdeps/nptl/sigfillset.c
>> +++ /dev/null
>> @@ -1,20 +0,0 @@
>> -/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
>> -   This file is part of the GNU C Library.
>> -
>> -   The GNU C Library is free software; you can redistribute it and/or
>> -   modify it under the terms of the GNU Lesser General Public
>> -   License as published by the Free Software Foundation; either
>> -   version 2.1 of the License, or (at your option) any later version.
>> -
>> -   The GNU C Library is distributed in the hope that it will be useful,
>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> -   Lesser General Public License for more details.
>> -
>> -   You should have received a copy of the GNU Lesser General Public
>> -   License along with the GNU C Library; if not, see
>> -   <http://www.gnu.org/licenses/>.  */
>> -
>> -#include <nptl/pthreadP.h>
>> -
>> -#include <signal/sigfillset.c>
>> diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c
>> index a4a0875..8a135c7 100644
>> --- a/sysdeps/posix/signal.c
>> +++ b/sysdeps/posix/signal.c
>> @@ -18,8 +18,8 @@
>>  
>>  #include <errno.h>
>>  #include <signal.h>
>> -#include <string.h>	/* For the real memset prototype.  */
>>  #include <sigsetops.h>
>> +#include <internal-signals.h>
>>  
>>  sigset_t _sigintr attribute_hidden;		/* Set by siginterrupt.  */
>>  
>> @@ -31,7 +31,8 @@ __bsd_signal (int sig, __sighandler_t handler)
>>    struct sigaction act, oact;
>>  
>>    /* Check signal extents to protect __sigismember.  */
>> -  if (handler == SIG_ERR || sig < 1 || sig >= NSIG)
>> +  if (handler == SIG_ERR || sig < 1 || sig >= NSIG
>> +      || __is_internal_signal (sig))
>>      {
>>        __set_errno (EINVAL);
>>        return SIG_ERR;
>> diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c
>> index b62aa3c..6ab4a48 100644
>> --- a/sysdeps/posix/sigset.c
>> +++ b/sysdeps/posix/sigset.c
>> @@ -31,15 +31,9 @@ sigset (int sig, __sighandler_t disp)
>>    sigset_t set;
>>    sigset_t oset;
>>  
>> -  /* Check signal extents to protect __sigismember.  */
>> -  if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
>> -    {
>> -      __set_errno (EINVAL);
>> -      return SIG_ERR;
>> -    }
>> -
>>    __sigemptyset (&set);
>> -  __sigaddset (&set, sig);
>> +  if (sigaddset (&set, sig) < 0)
>> +    return SIG_ERR;
>>  
>>    if (disp == SIG_HOLD)
>>      {
>> diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
>> index e007372..5ff4cf8 100644
>> --- a/sysdeps/unix/sysv/linux/internal-signals.h
>> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
>> @@ -21,6 +21,8 @@
>>  
>>  #include <signal.h>
>>  #include <sigsetops.h>
>> +#include <stdbool.h>
>> +#include <sysdep.h>
>>  
>>  /* The signal used for asynchronous cancelation.  */
>>  #define SIGCANCEL       __SIGRTMIN
>> @@ -37,7 +39,7 @@
>>  
>>  
>>  /* Return is sig is used internally.  */
>> -static inline int
>> +static inline bool
>>  __is_internal_signal (int sig)
>>  {
>>    return (sig == SIGCANCEL) || (sig == SIGSETXID);
>> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
>> index 051a285..b4de885 100644
>> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
>> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
>> @@ -24,21 +24,8 @@ int
>>  __sigtimedwait (const sigset_t *set, siginfo_t *info,
>>  		const struct timespec *timeout)
>>  {
>> -  sigset_t tmpset;
>> -  if (set != NULL
>> -      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
>> -	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
>> -    {
>> -      /* Create a temporary mask without the bit for SIGCANCEL set.  */
>> -      // We are not copying more than we have to.
>> -      memcpy (&tmpset, set, _NSIG / 8);
>> -      __sigdelset (&tmpset, SIGCANCEL);
>> -      __sigdelset (&tmpset, SIGSETXID);
>> -      set = &tmpset;
>> -    }
>> -
>> -    /* XXX The size argument hopefully will have to be changed to the
>> -       real size of the user-level sigset_t.  */
>> +  /* XXX The size argument hopefully will have to be changed to the
>> +     real size of the user-level sigset_t.  */
>>    int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
>>  
>>    /* The kernel generates a SI_TKILL code in si_code in case tkill is
>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391)
  2018-04-03 14:24     ` Adhemerval Zanella
@ 2018-04-03 15:12       ` Zack Weinberg
  2018-04-03 16:14         ` Adhemerval Zanella
  0 siblings, 1 reply; 15+ messages in thread
From: Zack Weinberg @ 2018-04-03 15:12 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

LGTM except I think sysdeps/generic/internal-signals.h should define
all of the functions that sysdeps/u/s/l/internal-signals.h does.

On Tue, Apr 3, 2018 at 10:24 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> If no one opposes, I will commit this shortly.
>
> On 19/02/2018 14:50, Adhemerval Zanella wrote:
>> Ping.
>>
>> On 12/02/2018 10:42, Adhemerval Zanella wrote:
>>> This patch filters out the internal NPTL signals (SIGCANCEL/SIGTIMER and
>>> SIGSETXID) from signal functions.  GLIBC on Linux requires both signals to
>>> proper implement pthread cancellation, posix timers, and set*id posix
>>> thread synchronization.
>>>
>>> And not filtering out the internal signal is troublesome:
>>>
>>>   - A conformant program on a architecture that does not filter out the
>>>     signals might inadvertently disable pthread asynchronous cancellation,
>>>     set*id synchronization or posix timers.
>>>
>>>   - It might also to security issues if SIGSETXID is masked and set*id
>>>     functions are called (some threads might have effective user or group
>>>     id different from the rest).
>>>
>>> The changes are basically:
>>>
>>>   - Change __is_internal_signal to bool and used on all signal function
>>>     that has a signal number as input.  Also for signal function which accepts
>>>     signals sets (sigset_t) it assumes that canonical function were used to
>>>     add/remove signals which lead to some input simplification.
>>>
>>>   - Fix tst-sigset.c to avoid check for SIGCANCEL/SIGTIMER and SIGSETXID.
>>>     It is rewritten to check each signal indidually and to check realtime
>>>     signals using canonical macros.
>>>
>>>   - Add generic __clear_internal_signals and __is_internal_signal
>>>     version since both symbols are used on generic implementations.
>>>
>>>   - Remove superflous sysdeps/nptl/sigfillset.c.
>>>
>>>   - Remove superflous SIGTIMER handling on Linux __is_internal_signal
>>>     since it is the same of SIGCANCEL.
>>>
>>>   - Remove dangling define and obvious comment on nptl/sigaction.c.
>>>
>>> Checked on x86_64-linux-gnu.
>>>
>>>      [BZ #22391]
>>>      * nptl/sigaction.c (__sigaction): Use __is_internal_signal to
>>>      check for internal nptl signals.
>>>      * signal/sigaddset.c (sigaddset): Likewise.
>>>      * signal/sigdelset.c (sigdelset): Likewise.
>>>      * sysdeps/posix/signal.c (__bsd_signal): Likewise.
>>>      * sysdeps/posix/sigset.c (sigset): Call and check sigaddset return
>>>      value.
>>>      * signal/sigfillset.c (sigfillset): User __clear_internal_signals
>>>      to filter out internal nptl signals.
>>>      * signal/tst-sigset.c (do_test): Check ech signal indidually and
>>>      also check realtime signals using standard macros.
>>>      * sysdeps/nptl/nptl-signals.h (__clear_internal_signals,
>>>      __is_internal_signal): New functions.
>>>      * sysdeps/nptl/sigfillset.c: Remove file.
>>>      * sysdeps/unix/sysv/linux/nptl-signals.h (__is_internal_signal):
>>>      Change return to bool.
>>>      (__clear_internal_signals): Remove SIGTIMER clean since it is
>>>      equal to SIGCANEL on Linux.
>>>      * sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Assume
>>>      signal set was constructed using standard functions.
>>>      * sysdeps/unix/sysv/linux/sigwait.c (do_sigtwait): Likewise.
>>>
>>> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>>> Reported-by: Yury Norov <ynorov@caviumnetworks.com>
>>> ---
>>>  ChangeLog                                  | 23 ++++++++
>>>  nptl/sigaction.c                           | 14 +----
>>>  signal/sigaction.c                         |  2 +-
>>>  signal/sigaddset.c                         |  5 +-
>>>  signal/sigdelset.c                         |  5 +-
>>>  signal/sigfillset.c                        | 10 +---
>>>  signal/tst-sigset.c                        | 92 ++++++++++++++++++++++--------
>>>  sysdeps/generic/internal-signals.h         | 11 ++++
>>>  sysdeps/nptl/sigfillset.c                  | 20 -------
>>>  sysdeps/posix/signal.c                     |  5 +-
>>>  sysdeps/posix/sigset.c                     | 10 +---
>>>  sysdeps/unix/sysv/linux/internal-signals.h |  4 +-
>>>  sysdeps/unix/sysv/linux/sigtimedwait.c     | 17 +-----
>>>  13 files changed, 122 insertions(+), 96 deletions(-)
>>>  delete mode 100644 sysdeps/nptl/sigfillset.c
>>>
>>> diff --git a/nptl/sigaction.c b/nptl/sigaction.c
>>> index ddf6f5e..79b6fdc 100644
>>> --- a/nptl/sigaction.c
>>> +++ b/nptl/sigaction.c
>>> @@ -16,22 +16,12 @@
>>>     License along with the GNU C Library; if not, see
>>>     <http://www.gnu.org/licenses/>.  */
>>>
>>> -
>>> -/* This is no complete implementation.  The file is meant to be
>>> -   included in the real implementation to provide the wrapper around
>>> -   __libc_sigaction.  */
>>> -
>>> -#include <nptl/pthreadP.h>
>>> -
>>> -/* We use the libc implementation but we tell it to not allow
>>> -   SIGCANCEL or SIGTIMER to be handled.  */
>>> -#define LIBC_SIGACTION      1
>>> -
>>> +#include <internal-signals.h>
>>>
>>>  int
>>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>>  {
>>> -  if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
>>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>>      {
>>>        __set_errno (EINVAL);
>>>        return -1;
>>> diff --git a/signal/sigaction.c b/signal/sigaction.c
>>> index f761ca2..c99001a 100644
>>> --- a/signal/sigaction.c
>>> +++ b/signal/sigaction.c
>>> @@ -24,7 +24,7 @@
>>>  int
>>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>>  {
>>> -  if (sig <= 0 || sig >= NSIG)
>>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>>      {
>>>        __set_errno (EINVAL);
>>>        return -1;
>>> diff --git a/signal/sigaddset.c b/signal/sigaddset.c
>>> index d310890..7238df4 100644
>>> --- a/signal/sigaddset.c
>>> +++ b/signal/sigaddset.c
>>> @@ -17,13 +17,14 @@
>>>
>>>  #include <errno.h>
>>>  #include <signal.h>
>>> -#include <sigsetops.h>
>>> +#include <internal-signals.h>
>>>
>>>  /* Add SIGNO to SET.  */
>>>  int
>>>  sigaddset (sigset_t *set, int signo)
>>>  {
>>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>>> +      || __is_internal_signal (signo))
>>>      {
>>>        __set_errno (EINVAL);
>>>        return -1;
>>> diff --git a/signal/sigdelset.c b/signal/sigdelset.c
>>> index cd83dda..011978c 100644
>>> --- a/signal/sigdelset.c
>>> +++ b/signal/sigdelset.c
>>> @@ -17,13 +17,14 @@
>>>
>>>  #include <errno.h>
>>>  #include <signal.h>
>>> -#include <sigsetops.h>
>>> +#include <internal-signals.h>
>>>
>>>  /* Add SIGNO to SET.  */
>>>  int
>>>  sigdelset (sigset_t *set, int signo)
>>>  {
>>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>>> +      || __is_internal_signal (signo))
>>>      {
>>>        __set_errno (EINVAL);
>>>        return -1;
>>> diff --git a/signal/sigfillset.c b/signal/sigfillset.c
>>> index e586fd9..83dd583 100644
>>> --- a/signal/sigfillset.c
>>> +++ b/signal/sigfillset.c
>>> @@ -18,6 +18,7 @@
>>>  #include <errno.h>
>>>  #include <signal.h>
>>>  #include <string.h>
>>> +#include <internal-signals.h>
>>>
>>>  /* Set all signals in SET.  */
>>>  int
>>> @@ -31,14 +32,7 @@ sigfillset (sigset_t *set)
>>>
>>>    memset (set, 0xff, sizeof (sigset_t));
>>>
>>> -  /* If the implementation uses a cancellation signal don't set the bit.  */
>>> -#ifdef SIGCANCEL
>>> -  __sigdelset (set, SIGCANCEL);
>>> -#endif
>>> -  /* Likewise for the signal to implement setxid.  */
>>> -#ifdef SIGSETXID
>>> -  __sigdelset (set, SIGSETXID);
>>> -#endif
>>> +  __clear_internal_signals (set);
>>>
>>>    return 0;
>>>  }
>>> diff --git a/signal/tst-sigset.c b/signal/tst-sigset.c
>>> index d47adcc..a2b764d 100644
>>> --- a/signal/tst-sigset.c
>>> +++ b/signal/tst-sigset.c
>>> @@ -1,43 +1,85 @@
>>>  /* Test sig*set functions.  */
>>>
>>>  #include <signal.h>
>>> -#include <stdio.h>
>>>
>>> -#define TEST_FUNCTION do_test ()
>>> +#include <support/check.h>
>>> +
>>>  static int
>>>  do_test (void)
>>>  {
>>> -  int result = 0;
>>> -  int sig = -1;
>>> +  sigset_t set;
>>> +  TEST_VERIFY (sigemptyset (&set) == 0);
>>>
>>> -#define TRY(call)                                                         \
>>> -  if (call)                                                               \
>>> -    {                                                                             \
>>> -      printf ("%s (sig = %d): %m\n", #call, sig);                         \
>>> -      result = 1;                                                         \
>>> -    }                                                                             \
>>> -  else
>>> +#define VERIFY(set, sig)                    \
>>> +  TEST_VERIFY (sigismember (&set, sig) == 0);       \
>>> +  TEST_VERIFY (sigaddset (&set, sig) == 0); \
>>> +  TEST_VERIFY (sigismember (&set, sig) != 0);       \
>>> +  TEST_VERIFY (sigdelset (&set, sig) == 0); \
>>> +  TEST_VERIFY (sigismember (&set, sig) == 0)
>>>
>>> +  /* ISO C99 signals.  */
>>> +  VERIFY (set, SIGINT);
>>> +  VERIFY (set, SIGILL);
>>> +  VERIFY (set, SIGABRT);
>>> +  VERIFY (set, SIGFPE);
>>> +  VERIFY (set, SIGSEGV);
>>> +  VERIFY (set, SIGTERM);
>>>
>>> -  sigset_t set;
>>> -  TRY (sigemptyset (&set) != 0);
>>> +  /* Historical signals specified by POSIX. */
>>> +  VERIFY (set, SIGHUP);
>>> +  VERIFY (set, SIGQUIT);
>>> +  VERIFY (set, SIGTRAP);
>>> +  VERIFY (set, SIGKILL);
>>> +  VERIFY (set, SIGBUS);
>>> +  VERIFY (set, SIGSYS);
>>> +  VERIFY (set, SIGPIPE);
>>> +  VERIFY (set, SIGALRM);
>>> +
>>> +  /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
>>> +  VERIFY (set, SIGURG);
>>> +  VERIFY (set, SIGSTOP);
>>> +  VERIFY (set, SIGTSTP);
>>> +  VERIFY (set, SIGCONT);
>>> +  VERIFY (set, SIGCHLD);
>>> +  VERIFY (set, SIGTTIN);
>>> +  VERIFY (set, SIGTTOU);
>>> +  VERIFY (set, SIGPOLL);
>>> +  VERIFY (set, SIGXCPU);
>>> +  VERIFY (set, SIGXFSZ);
>>> +  VERIFY (set, SIGVTALRM);
>>> +  VERIFY (set, SIGPROF);
>>> +  VERIFY (set, SIGUSR1);
>>> +  VERIFY (set, SIGUSR2);
>>> +
>>> +  /* Nonstandard signals found in all modern POSIX systems
>>> +     (including both BSD and Linux).  */
>>> +  VERIFY (set, SIGWINCH);
>>>
>>> -#ifdef SIGRTMAX
>>> -  int max_sig = SIGRTMAX;
>>> -#else
>>> -  int max_sig = NSIG - 1;
>>> +  /* Arch-specific signals.  */
>>> +#ifdef SIGEMT
>>> +  VERIFY (set, SIGEMT);
>>> +#endif
>>> +#ifdef SIGLOST
>>> +  VERIFY (set, SIGLOST);
>>> +#endif
>>> +#ifdef SIGINFO
>>> +  VERIFY (set, SIGINFO);
>>> +#endif
>>> +#ifdef SIGSTKFLT
>>> +  VERIFY (set, SIGSTKFLT);
>>> +#endif
>>> +#ifdef SIGPWR
>>> +  VERIFY (set, SIGPWR);
>>>  #endif
>>>
>>> -  for (sig = 1; sig <= max_sig; ++sig)
>>> +  /* Read-time signals (POSIX.1b real-time extensions).  If they are
>>> +     supported SIGRTMAX value is greater than SIGRTMIN.  */
>>> +  for (int rtsig = SIGRTMIN; rtsig <= SIGRTMAX; rtsig++)
>>>      {
>>> -      TRY (sigismember (&set, sig) != 0);
>>> -      TRY (sigaddset (&set, sig) != 0);
>>> -      TRY (sigismember (&set, sig) == 0);
>>> -      TRY (sigdelset (&set, sig) != 0);
>>> -      TRY (sigismember (&set, sig) != 0);
>>> +      VERIFY (set, rtsig);
>>>      }
>>>
>>> -  return result;
>>> +  return 0;
>>>  }
>>>
>>> -#include "../test-skeleton.c"
>>> +#include <support/test-driver.c>
>>> diff --git a/sysdeps/generic/internal-signals.h b/sysdeps/generic/internal-signals.h
>>> index 01e5b75..ab0b22e 100644
>>> --- a/sysdeps/generic/internal-signals.h
>>> +++ b/sysdeps/generic/internal-signals.h
>>> @@ -15,3 +15,14 @@
>>>     You should have received a copy of the GNU Lesser General Public
>>>     License along with the GNU C Library; if not, see
>>>     <http://www.gnu.org/licenses/>.  */
>>> +
>>> +static inline void
>>> +__clear_internal_signals (sigset_t *set)
>>> +{
>>> +}
>>> +
>>> +static inline bool
>>> +__is_internal_signal (int sig)
>>> +{
>>> +  return false;
>>> +}
>>> diff --git a/sysdeps/nptl/sigfillset.c b/sysdeps/nptl/sigfillset.c
>>> deleted file mode 100644
>>> index 94a7680..0000000
>>> --- a/sysdeps/nptl/sigfillset.c
>>> +++ /dev/null
>>> @@ -1,20 +0,0 @@
>>> -/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
>>> -   This file is part of the GNU C Library.
>>> -
>>> -   The GNU C Library is free software; you can redistribute it and/or
>>> -   modify it under the terms of the GNU Lesser General Public
>>> -   License as published by the Free Software Foundation; either
>>> -   version 2.1 of the License, or (at your option) any later version.
>>> -
>>> -   The GNU C Library is distributed in the hope that it will be useful,
>>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> -   Lesser General Public License for more details.
>>> -
>>> -   You should have received a copy of the GNU Lesser General Public
>>> -   License along with the GNU C Library; if not, see
>>> -   <http://www.gnu.org/licenses/>.  */
>>> -
>>> -#include <nptl/pthreadP.h>
>>> -
>>> -#include <signal/sigfillset.c>
>>> diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c
>>> index a4a0875..8a135c7 100644
>>> --- a/sysdeps/posix/signal.c
>>> +++ b/sysdeps/posix/signal.c
>>> @@ -18,8 +18,8 @@
>>>
>>>  #include <errno.h>
>>>  #include <signal.h>
>>> -#include <string.h> /* For the real memset prototype.  */
>>>  #include <sigsetops.h>
>>> +#include <internal-signals.h>
>>>
>>>  sigset_t _sigintr attribute_hidden;         /* Set by siginterrupt.  */
>>>
>>> @@ -31,7 +31,8 @@ __bsd_signal (int sig, __sighandler_t handler)
>>>    struct sigaction act, oact;
>>>
>>>    /* Check signal extents to protect __sigismember.  */
>>> -  if (handler == SIG_ERR || sig < 1 || sig >= NSIG)
>>> +  if (handler == SIG_ERR || sig < 1 || sig >= NSIG
>>> +      || __is_internal_signal (sig))
>>>      {
>>>        __set_errno (EINVAL);
>>>        return SIG_ERR;
>>> diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c
>>> index b62aa3c..6ab4a48 100644
>>> --- a/sysdeps/posix/sigset.c
>>> +++ b/sysdeps/posix/sigset.c
>>> @@ -31,15 +31,9 @@ sigset (int sig, __sighandler_t disp)
>>>    sigset_t set;
>>>    sigset_t oset;
>>>
>>> -  /* Check signal extents to protect __sigismember.  */
>>> -  if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
>>> -    {
>>> -      __set_errno (EINVAL);
>>> -      return SIG_ERR;
>>> -    }
>>> -
>>>    __sigemptyset (&set);
>>> -  __sigaddset (&set, sig);
>>> +  if (sigaddset (&set, sig) < 0)
>>> +    return SIG_ERR;
>>>
>>>    if (disp == SIG_HOLD)
>>>      {
>>> diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
>>> index e007372..5ff4cf8 100644
>>> --- a/sysdeps/unix/sysv/linux/internal-signals.h
>>> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
>>> @@ -21,6 +21,8 @@
>>>
>>>  #include <signal.h>
>>>  #include <sigsetops.h>
>>> +#include <stdbool.h>
>>> +#include <sysdep.h>
>>>
>>>  /* The signal used for asynchronous cancelation.  */
>>>  #define SIGCANCEL       __SIGRTMIN
>>> @@ -37,7 +39,7 @@
>>>
>>>
>>>  /* Return is sig is used internally.  */
>>> -static inline int
>>> +static inline bool
>>>  __is_internal_signal (int sig)
>>>  {
>>>    return (sig == SIGCANCEL) || (sig == SIGSETXID);
>>> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
>>> index 051a285..b4de885 100644
>>> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
>>> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
>>> @@ -24,21 +24,8 @@ int
>>>  __sigtimedwait (const sigset_t *set, siginfo_t *info,
>>>              const struct timespec *timeout)
>>>  {
>>> -  sigset_t tmpset;
>>> -  if (set != NULL
>>> -      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
>>> -      || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
>>> -    {
>>> -      /* Create a temporary mask without the bit for SIGCANCEL set.  */
>>> -      // We are not copying more than we have to.
>>> -      memcpy (&tmpset, set, _NSIG / 8);
>>> -      __sigdelset (&tmpset, SIGCANCEL);
>>> -      __sigdelset (&tmpset, SIGSETXID);
>>> -      set = &tmpset;
>>> -    }
>>> -
>>> -    /* XXX The size argument hopefully will have to be changed to the
>>> -       real size of the user-level sigset_t.  */
>>> +  /* XXX The size argument hopefully will have to be changed to the
>>> +     real size of the user-level sigset_t.  */
>>>    int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
>>>
>>>    /* The kernel generates a SI_TKILL code in si_code in case tkill is
>>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391)
  2018-04-03 15:12       ` Zack Weinberg
@ 2018-04-03 16:14         ` Adhemerval Zanella
  0 siblings, 0 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-04-03 16:14 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

Right, I will fix it.

On 03/04/2018 12:12, Zack Weinberg wrote:
> LGTM except I think sysdeps/generic/internal-signals.h should define
> all of the functions that sysdeps/u/s/l/internal-signals.h does.
> 
> On Tue, Apr 3, 2018 at 10:24 AM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> If no one opposes, I will commit this shortly.
>>
>> On 19/02/2018 14:50, Adhemerval Zanella wrote:
>>> Ping.
>>>
>>> On 12/02/2018 10:42, Adhemerval Zanella wrote:
>>>> This patch filters out the internal NPTL signals (SIGCANCEL/SIGTIMER and
>>>> SIGSETXID) from signal functions.  GLIBC on Linux requires both signals to
>>>> proper implement pthread cancellation, posix timers, and set*id posix
>>>> thread synchronization.
>>>>
>>>> And not filtering out the internal signal is troublesome:
>>>>
>>>>   - A conformant program on a architecture that does not filter out the
>>>>     signals might inadvertently disable pthread asynchronous cancellation,
>>>>     set*id synchronization or posix timers.
>>>>
>>>>   - It might also to security issues if SIGSETXID is masked and set*id
>>>>     functions are called (some threads might have effective user or group
>>>>     id different from the rest).
>>>>
>>>> The changes are basically:
>>>>
>>>>   - Change __is_internal_signal to bool and used on all signal function
>>>>     that has a signal number as input.  Also for signal function which accepts
>>>>     signals sets (sigset_t) it assumes that canonical function were used to
>>>>     add/remove signals which lead to some input simplification.
>>>>
>>>>   - Fix tst-sigset.c to avoid check for SIGCANCEL/SIGTIMER and SIGSETXID.
>>>>     It is rewritten to check each signal indidually and to check realtime
>>>>     signals using canonical macros.
>>>>
>>>>   - Add generic __clear_internal_signals and __is_internal_signal
>>>>     version since both symbols are used on generic implementations.
>>>>
>>>>   - Remove superflous sysdeps/nptl/sigfillset.c.
>>>>
>>>>   - Remove superflous SIGTIMER handling on Linux __is_internal_signal
>>>>     since it is the same of SIGCANCEL.
>>>>
>>>>   - Remove dangling define and obvious comment on nptl/sigaction.c.
>>>>
>>>> Checked on x86_64-linux-gnu.
>>>>
>>>>      [BZ #22391]
>>>>      * nptl/sigaction.c (__sigaction): Use __is_internal_signal to
>>>>      check for internal nptl signals.
>>>>      * signal/sigaddset.c (sigaddset): Likewise.
>>>>      * signal/sigdelset.c (sigdelset): Likewise.
>>>>      * sysdeps/posix/signal.c (__bsd_signal): Likewise.
>>>>      * sysdeps/posix/sigset.c (sigset): Call and check sigaddset return
>>>>      value.
>>>>      * signal/sigfillset.c (sigfillset): User __clear_internal_signals
>>>>      to filter out internal nptl signals.
>>>>      * signal/tst-sigset.c (do_test): Check ech signal indidually and
>>>>      also check realtime signals using standard macros.
>>>>      * sysdeps/nptl/nptl-signals.h (__clear_internal_signals,
>>>>      __is_internal_signal): New functions.
>>>>      * sysdeps/nptl/sigfillset.c: Remove file.
>>>>      * sysdeps/unix/sysv/linux/nptl-signals.h (__is_internal_signal):
>>>>      Change return to bool.
>>>>      (__clear_internal_signals): Remove SIGTIMER clean since it is
>>>>      equal to SIGCANEL on Linux.
>>>>      * sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Assume
>>>>      signal set was constructed using standard functions.
>>>>      * sysdeps/unix/sysv/linux/sigwait.c (do_sigtwait): Likewise.
>>>>
>>>> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>>>> Reported-by: Yury Norov <ynorov@caviumnetworks.com>
>>>> ---
>>>>  ChangeLog                                  | 23 ++++++++
>>>>  nptl/sigaction.c                           | 14 +----
>>>>  signal/sigaction.c                         |  2 +-
>>>>  signal/sigaddset.c                         |  5 +-
>>>>  signal/sigdelset.c                         |  5 +-
>>>>  signal/sigfillset.c                        | 10 +---
>>>>  signal/tst-sigset.c                        | 92 ++++++++++++++++++++++--------
>>>>  sysdeps/generic/internal-signals.h         | 11 ++++
>>>>  sysdeps/nptl/sigfillset.c                  | 20 -------
>>>>  sysdeps/posix/signal.c                     |  5 +-
>>>>  sysdeps/posix/sigset.c                     | 10 +---
>>>>  sysdeps/unix/sysv/linux/internal-signals.h |  4 +-
>>>>  sysdeps/unix/sysv/linux/sigtimedwait.c     | 17 +-----
>>>>  13 files changed, 122 insertions(+), 96 deletions(-)
>>>>  delete mode 100644 sysdeps/nptl/sigfillset.c
>>>>
>>>> diff --git a/nptl/sigaction.c b/nptl/sigaction.c
>>>> index ddf6f5e..79b6fdc 100644
>>>> --- a/nptl/sigaction.c
>>>> +++ b/nptl/sigaction.c
>>>> @@ -16,22 +16,12 @@
>>>>     License along with the GNU C Library; if not, see
>>>>     <http://www.gnu.org/licenses/>.  */
>>>>
>>>> -
>>>> -/* This is no complete implementation.  The file is meant to be
>>>> -   included in the real implementation to provide the wrapper around
>>>> -   __libc_sigaction.  */
>>>> -
>>>> -#include <nptl/pthreadP.h>
>>>> -
>>>> -/* We use the libc implementation but we tell it to not allow
>>>> -   SIGCANCEL or SIGTIMER to be handled.  */
>>>> -#define LIBC_SIGACTION      1
>>>> -
>>>> +#include <internal-signals.h>
>>>>
>>>>  int
>>>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>>>  {
>>>> -  if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
>>>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>>>      {
>>>>        __set_errno (EINVAL);
>>>>        return -1;
>>>> diff --git a/signal/sigaction.c b/signal/sigaction.c
>>>> index f761ca2..c99001a 100644
>>>> --- a/signal/sigaction.c
>>>> +++ b/signal/sigaction.c
>>>> @@ -24,7 +24,7 @@
>>>>  int
>>>>  __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>>>  {
>>>> -  if (sig <= 0 || sig >= NSIG)
>>>> +  if (sig <= 0 || sig >= NSIG || __is_internal_signal (sig))
>>>>      {
>>>>        __set_errno (EINVAL);
>>>>        return -1;
>>>> diff --git a/signal/sigaddset.c b/signal/sigaddset.c
>>>> index d310890..7238df4 100644
>>>> --- a/signal/sigaddset.c
>>>> +++ b/signal/sigaddset.c
>>>> @@ -17,13 +17,14 @@
>>>>
>>>>  #include <errno.h>
>>>>  #include <signal.h>
>>>> -#include <sigsetops.h>
>>>> +#include <internal-signals.h>
>>>>
>>>>  /* Add SIGNO to SET.  */
>>>>  int
>>>>  sigaddset (sigset_t *set, int signo)
>>>>  {
>>>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>>>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>>>> +      || __is_internal_signal (signo))
>>>>      {
>>>>        __set_errno (EINVAL);
>>>>        return -1;
>>>> diff --git a/signal/sigdelset.c b/signal/sigdelset.c
>>>> index cd83dda..011978c 100644
>>>> --- a/signal/sigdelset.c
>>>> +++ b/signal/sigdelset.c
>>>> @@ -17,13 +17,14 @@
>>>>
>>>>  #include <errno.h>
>>>>  #include <signal.h>
>>>> -#include <sigsetops.h>
>>>> +#include <internal-signals.h>
>>>>
>>>>  /* Add SIGNO to SET.  */
>>>>  int
>>>>  sigdelset (sigset_t *set, int signo)
>>>>  {
>>>> -  if (set == NULL || signo <= 0 || signo >= NSIG)
>>>> +  if (set == NULL || signo <= 0 || signo >= NSIG
>>>> +      || __is_internal_signal (signo))
>>>>      {
>>>>        __set_errno (EINVAL);
>>>>        return -1;
>>>> diff --git a/signal/sigfillset.c b/signal/sigfillset.c
>>>> index e586fd9..83dd583 100644
>>>> --- a/signal/sigfillset.c
>>>> +++ b/signal/sigfillset.c
>>>> @@ -18,6 +18,7 @@
>>>>  #include <errno.h>
>>>>  #include <signal.h>
>>>>  #include <string.h>
>>>> +#include <internal-signals.h>
>>>>
>>>>  /* Set all signals in SET.  */
>>>>  int
>>>> @@ -31,14 +32,7 @@ sigfillset (sigset_t *set)
>>>>
>>>>    memset (set, 0xff, sizeof (sigset_t));
>>>>
>>>> -  /* If the implementation uses a cancellation signal don't set the bit.  */
>>>> -#ifdef SIGCANCEL
>>>> -  __sigdelset (set, SIGCANCEL);
>>>> -#endif
>>>> -  /* Likewise for the signal to implement setxid.  */
>>>> -#ifdef SIGSETXID
>>>> -  __sigdelset (set, SIGSETXID);
>>>> -#endif
>>>> +  __clear_internal_signals (set);
>>>>
>>>>    return 0;
>>>>  }
>>>> diff --git a/signal/tst-sigset.c b/signal/tst-sigset.c
>>>> index d47adcc..a2b764d 100644
>>>> --- a/signal/tst-sigset.c
>>>> +++ b/signal/tst-sigset.c
>>>> @@ -1,43 +1,85 @@
>>>>  /* Test sig*set functions.  */
>>>>
>>>>  #include <signal.h>
>>>> -#include <stdio.h>
>>>>
>>>> -#define TEST_FUNCTION do_test ()
>>>> +#include <support/check.h>
>>>> +
>>>>  static int
>>>>  do_test (void)
>>>>  {
>>>> -  int result = 0;
>>>> -  int sig = -1;
>>>> +  sigset_t set;
>>>> +  TEST_VERIFY (sigemptyset (&set) == 0);
>>>>
>>>> -#define TRY(call)                                                         \
>>>> -  if (call)                                                               \
>>>> -    {                                                                             \
>>>> -      printf ("%s (sig = %d): %m\n", #call, sig);                         \
>>>> -      result = 1;                                                         \
>>>> -    }                                                                             \
>>>> -  else
>>>> +#define VERIFY(set, sig)                    \
>>>> +  TEST_VERIFY (sigismember (&set, sig) == 0);       \
>>>> +  TEST_VERIFY (sigaddset (&set, sig) == 0); \
>>>> +  TEST_VERIFY (sigismember (&set, sig) != 0);       \
>>>> +  TEST_VERIFY (sigdelset (&set, sig) == 0); \
>>>> +  TEST_VERIFY (sigismember (&set, sig) == 0)
>>>>
>>>> +  /* ISO C99 signals.  */
>>>> +  VERIFY (set, SIGINT);
>>>> +  VERIFY (set, SIGILL);
>>>> +  VERIFY (set, SIGABRT);
>>>> +  VERIFY (set, SIGFPE);
>>>> +  VERIFY (set, SIGSEGV);
>>>> +  VERIFY (set, SIGTERM);
>>>>
>>>> -  sigset_t set;
>>>> -  TRY (sigemptyset (&set) != 0);
>>>> +  /* Historical signals specified by POSIX. */
>>>> +  VERIFY (set, SIGHUP);
>>>> +  VERIFY (set, SIGQUIT);
>>>> +  VERIFY (set, SIGTRAP);
>>>> +  VERIFY (set, SIGKILL);
>>>> +  VERIFY (set, SIGBUS);
>>>> +  VERIFY (set, SIGSYS);
>>>> +  VERIFY (set, SIGPIPE);
>>>> +  VERIFY (set, SIGALRM);
>>>> +
>>>> +  /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
>>>> +  VERIFY (set, SIGURG);
>>>> +  VERIFY (set, SIGSTOP);
>>>> +  VERIFY (set, SIGTSTP);
>>>> +  VERIFY (set, SIGCONT);
>>>> +  VERIFY (set, SIGCHLD);
>>>> +  VERIFY (set, SIGTTIN);
>>>> +  VERIFY (set, SIGTTOU);
>>>> +  VERIFY (set, SIGPOLL);
>>>> +  VERIFY (set, SIGXCPU);
>>>> +  VERIFY (set, SIGXFSZ);
>>>> +  VERIFY (set, SIGVTALRM);
>>>> +  VERIFY (set, SIGPROF);
>>>> +  VERIFY (set, SIGUSR1);
>>>> +  VERIFY (set, SIGUSR2);
>>>> +
>>>> +  /* Nonstandard signals found in all modern POSIX systems
>>>> +     (including both BSD and Linux).  */
>>>> +  VERIFY (set, SIGWINCH);
>>>>
>>>> -#ifdef SIGRTMAX
>>>> -  int max_sig = SIGRTMAX;
>>>> -#else
>>>> -  int max_sig = NSIG - 1;
>>>> +  /* Arch-specific signals.  */
>>>> +#ifdef SIGEMT
>>>> +  VERIFY (set, SIGEMT);
>>>> +#endif
>>>> +#ifdef SIGLOST
>>>> +  VERIFY (set, SIGLOST);
>>>> +#endif
>>>> +#ifdef SIGINFO
>>>> +  VERIFY (set, SIGINFO);
>>>> +#endif
>>>> +#ifdef SIGSTKFLT
>>>> +  VERIFY (set, SIGSTKFLT);
>>>> +#endif
>>>> +#ifdef SIGPWR
>>>> +  VERIFY (set, SIGPWR);
>>>>  #endif
>>>>
>>>> -  for (sig = 1; sig <= max_sig; ++sig)
>>>> +  /* Read-time signals (POSIX.1b real-time extensions).  If they are
>>>> +     supported SIGRTMAX value is greater than SIGRTMIN.  */
>>>> +  for (int rtsig = SIGRTMIN; rtsig <= SIGRTMAX; rtsig++)
>>>>      {
>>>> -      TRY (sigismember (&set, sig) != 0);
>>>> -      TRY (sigaddset (&set, sig) != 0);
>>>> -      TRY (sigismember (&set, sig) == 0);
>>>> -      TRY (sigdelset (&set, sig) != 0);
>>>> -      TRY (sigismember (&set, sig) != 0);
>>>> +      VERIFY (set, rtsig);
>>>>      }
>>>>
>>>> -  return result;
>>>> +  return 0;
>>>>  }
>>>>
>>>> -#include "../test-skeleton.c"
>>>> +#include <support/test-driver.c>
>>>> diff --git a/sysdeps/generic/internal-signals.h b/sysdeps/generic/internal-signals.h
>>>> index 01e5b75..ab0b22e 100644
>>>> --- a/sysdeps/generic/internal-signals.h
>>>> +++ b/sysdeps/generic/internal-signals.h
>>>> @@ -15,3 +15,14 @@
>>>>     You should have received a copy of the GNU Lesser General Public
>>>>     License along with the GNU C Library; if not, see
>>>>     <http://www.gnu.org/licenses/>.  */
>>>> +
>>>> +static inline void
>>>> +__clear_internal_signals (sigset_t *set)
>>>> +{
>>>> +}
>>>> +
>>>> +static inline bool
>>>> +__is_internal_signal (int sig)
>>>> +{
>>>> +  return false;
>>>> +}
>>>> diff --git a/sysdeps/nptl/sigfillset.c b/sysdeps/nptl/sigfillset.c
>>>> deleted file mode 100644
>>>> index 94a7680..0000000
>>>> --- a/sysdeps/nptl/sigfillset.c
>>>> +++ /dev/null
>>>> @@ -1,20 +0,0 @@
>>>> -/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
>>>> -   This file is part of the GNU C Library.
>>>> -
>>>> -   The GNU C Library is free software; you can redistribute it and/or
>>>> -   modify it under the terms of the GNU Lesser General Public
>>>> -   License as published by the Free Software Foundation; either
>>>> -   version 2.1 of the License, or (at your option) any later version.
>>>> -
>>>> -   The GNU C Library is distributed in the hope that it will be useful,
>>>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> -   Lesser General Public License for more details.
>>>> -
>>>> -   You should have received a copy of the GNU Lesser General Public
>>>> -   License along with the GNU C Library; if not, see
>>>> -   <http://www.gnu.org/licenses/>.  */
>>>> -
>>>> -#include <nptl/pthreadP.h>
>>>> -
>>>> -#include <signal/sigfillset.c>
>>>> diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c
>>>> index a4a0875..8a135c7 100644
>>>> --- a/sysdeps/posix/signal.c
>>>> +++ b/sysdeps/posix/signal.c
>>>> @@ -18,8 +18,8 @@
>>>>
>>>>  #include <errno.h>
>>>>  #include <signal.h>
>>>> -#include <string.h> /* For the real memset prototype.  */
>>>>  #include <sigsetops.h>
>>>> +#include <internal-signals.h>
>>>>
>>>>  sigset_t _sigintr attribute_hidden;         /* Set by siginterrupt.  */
>>>>
>>>> @@ -31,7 +31,8 @@ __bsd_signal (int sig, __sighandler_t handler)
>>>>    struct sigaction act, oact;
>>>>
>>>>    /* Check signal extents to protect __sigismember.  */
>>>> -  if (handler == SIG_ERR || sig < 1 || sig >= NSIG)
>>>> +  if (handler == SIG_ERR || sig < 1 || sig >= NSIG
>>>> +      || __is_internal_signal (sig))
>>>>      {
>>>>        __set_errno (EINVAL);
>>>>        return SIG_ERR;
>>>> diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c
>>>> index b62aa3c..6ab4a48 100644
>>>> --- a/sysdeps/posix/sigset.c
>>>> +++ b/sysdeps/posix/sigset.c
>>>> @@ -31,15 +31,9 @@ sigset (int sig, __sighandler_t disp)
>>>>    sigset_t set;
>>>>    sigset_t oset;
>>>>
>>>> -  /* Check signal extents to protect __sigismember.  */
>>>> -  if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
>>>> -    {
>>>> -      __set_errno (EINVAL);
>>>> -      return SIG_ERR;
>>>> -    }
>>>> -
>>>>    __sigemptyset (&set);
>>>> -  __sigaddset (&set, sig);
>>>> +  if (sigaddset (&set, sig) < 0)
>>>> +    return SIG_ERR;
>>>>
>>>>    if (disp == SIG_HOLD)
>>>>      {
>>>> diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
>>>> index e007372..5ff4cf8 100644
>>>> --- a/sysdeps/unix/sysv/linux/internal-signals.h
>>>> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
>>>> @@ -21,6 +21,8 @@
>>>>
>>>>  #include <signal.h>
>>>>  #include <sigsetops.h>
>>>> +#include <stdbool.h>
>>>> +#include <sysdep.h>
>>>>
>>>>  /* The signal used for asynchronous cancelation.  */
>>>>  #define SIGCANCEL       __SIGRTMIN
>>>> @@ -37,7 +39,7 @@
>>>>
>>>>
>>>>  /* Return is sig is used internally.  */
>>>> -static inline int
>>>> +static inline bool
>>>>  __is_internal_signal (int sig)
>>>>  {
>>>>    return (sig == SIGCANCEL) || (sig == SIGSETXID);
>>>> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
>>>> index 051a285..b4de885 100644
>>>> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
>>>> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
>>>> @@ -24,21 +24,8 @@ int
>>>>  __sigtimedwait (const sigset_t *set, siginfo_t *info,
>>>>              const struct timespec *timeout)
>>>>  {
>>>> -  sigset_t tmpset;
>>>> -  if (set != NULL
>>>> -      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
>>>> -      || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
>>>> -    {
>>>> -      /* Create a temporary mask without the bit for SIGCANCEL set.  */
>>>> -      // We are not copying more than we have to.
>>>> -      memcpy (&tmpset, set, _NSIG / 8);
>>>> -      __sigdelset (&tmpset, SIGCANCEL);
>>>> -      __sigdelset (&tmpset, SIGSETXID);
>>>> -      set = &tmpset;
>>>> -    }
>>>> -
>>>> -    /* XXX The size argument hopefully will have to be changed to the
>>>> -       real size of the user-level sigset_t.  */
>>>> +  /* XXX The size argument hopefully will have to be changed to the
>>>> +     real size of the user-level sigset_t.  */
>>>>    int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
>>>>
>>>>    /* The kernel generates a SI_TKILL code in si_code in case tkill is
>>>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 3/4] linux: Consolidate sigaction implementation
  2018-02-19 17:54   ` Adhemerval Zanella
@ 2018-04-05 18:23     ` Adhemerval Zanella
  0 siblings, 0 replies; 15+ messages in thread
From: Adhemerval Zanella @ 2018-04-05 18:23 UTC (permalink / raw)
  To: libc-alpha

If no one opposes it, I will commit this shortly.

On 19/02/2018 14:50, Adhemerval Zanella wrote:
> Ping.
> 
> On 12/02/2018 10:42, Adhemerval Zanella wrote:
>> This patch consolidates all Linux sigaction implementation on a default
>> one at sysdeps/unix/sysv/linux/sigaction.c.  The idea is remove redundant
>> code and simplify new ports addition by following the current generic
>> Linux User API (UAPI).
>>
>> The UAPI for new ports defines a generic extensible sigaction struct as:
>>
>>   struct sigaction
>>   {
>>     __sighandler_t sa_handler;
>>     unsigned long sa_flags;
>>   #ifdef SA_RESTORER
>>     void (*sa_restorer) (void);
>>   #endif
>>     sigset_t sa_mask;
>>   };
>>
>> Where SA_RESTORER is just placed to compatibility reasons, news ports
>> should not add it.  A similar definition is used on generic
>> kernel_sigaction.h.
>>
>> The user exported sigaction definition is not changed, so for most
>> architectures it requires an adjustment to kernel expected one for the
>> syscall.
>>
>> The main changes are:
>>
>>   - All architectures now define and use a kernel_sigaction struct meant
>>     for the syscall, even for the architectures where the user sigaction
>>     has the same layout of the kernel expected one (s390-64 and ia64).
>>     Although it requires more work for these architectures, it simplifies
>>     the generic implementation. Also, sigaction is hardly a hotspot where
>>     micro optimization would play an important role.
>>
>>   - The generic kernel_sigaction definition is now aligned with expected
>>     UAPI one for newer ports, where SA_RESTORER and sa_restorer is not
>>     expected to be defined.  This means adding kernel_sigaction for
>>     current architectures that does define it (m68k, nios2, powerpc, s390,
>>     sh, sparc, and tile) and which rely on previous generic definition.
>>
>>   - Remove old MIPS usage of sa_restorer.  This was removed since 2.6.27
>>     (2957c9e61ee9c - "[MIPS] IRIX: Goodbye and thanks for all the fish").
>>
>> So for new ports the generic implementation should work if its uses
>> Linux UAPI.  If SA_RESTORER is still required (due some architecture
>> limitation), it should define its own kernel_sigaction.h, define it and
>> include generic header (assuming it still uses the default generic kernel
>> layout).
>>
>> Checked on x86_64-linux-gnu, i686-linux-gnu, arm-linux-gnueabihf,
>> aarch64-linux-gnu, sparc64-linux-gnu, sparcv9-linux-gnu, powerpc-linux-gnu,
>> and powerpc64-linux-gnu.  I also check the build on all remaining affected
>> ABIs.
>>
>> 	* sysdeps/unix/sysv/linux/aarch64/sigaction.c: Use default Linux version
>> 	as base implementation.
>> 	* sysdeps/unix/sysv/linux/arm/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h: Add include guards,
>> 	remove unrequired definitions and update comments.
>> 	* sysdeps/unix/sysv/linux/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/mips/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h: New file.
>> 	* sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/kernel_sigaction: Likewise.
>> 	* sysdeps/unix/sysv/linux/s390/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/sh/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/tile/kernel_sigaction.h: Likewise.
>> 	* sysdeps/unix/sysv/linux/ia64/sigaction.c: Remove file.
>> 	* sysdeps/unix/sysv/linux/mips/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/sigaction.c: Add STUB, SET_SA_RESTORER,
>> 	and RESET_SA_RESTORER hooks.
>>
>> Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>> ---
>>  ChangeLog                                          |  25 +++++
>>  sysdeps/unix/sysv/linux/aarch64/sigaction.c        |  58 ++---------
>>  sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h   |  21 ++--
>>  sysdeps/unix/sysv/linux/arm/sigaction.c            |  79 +++-----------
>>  sysdeps/unix/sysv/linux/i386/sigaction.c           |  76 +++-----------
>>  sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h    |   6 ++
>>  sysdeps/unix/sysv/linux/ia64/sigaction.c           |  45 --------
>>  sysdeps/unix/sysv/linux/kernel_sigaction.h         |  31 +++---
>>  sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h    |  22 ++++
>>  sysdeps/unix/sysv/linux/mips/kernel_sigaction.h    |  48 ++-------
>>  sysdeps/unix/sysv/linux/mips/sigaction.c           | 116 ---------------------
>>  sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h   |   8 ++
>>  sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h |   8 ++
>>  sysdeps/unix/sysv/linux/s390/kernel_sigaction.h    |  28 +++++
>>  sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c   |  43 --------
>>  sysdeps/unix/sysv/linux/sh/kernel_sigaction.h      |   8 ++
>>  sysdeps/unix/sysv/linux/sigaction.c                |  28 ++---
>>  sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h   |  10 ++
>>  sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c  |  41 +-------
>>  sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c  |  43 +-------
>>  sysdeps/unix/sysv/linux/tile/kernel_sigaction.h    |   9 ++
>>  sysdeps/unix/sysv/linux/x86_64/sigaction.c         |  61 ++---------
>>  22 files changed, 230 insertions(+), 584 deletions(-)
>>  create mode 100644 sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
>>  delete mode 100644 sysdeps/unix/sysv/linux/ia64/sigaction.c
>>  create mode 100644 sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
>>  delete mode 100644 sysdeps/unix/sysv/linux/mips/sigaction.c
>>  create mode 100644 sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
>>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
>>  create mode 100644 sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
>>  delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
>>  create mode 100644 sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
>>  create mode 100644 sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
>>  create mode 100644 sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
>>
>> diff --git a/sysdeps/unix/sysv/linux/aarch64/sigaction.c b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
>> index 73f4eb7..83d5b4f 100644
>> --- a/sysdeps/unix/sysv/linux/aarch64/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
>> @@ -1,5 +1,4 @@
>>  /* Copyright (C) 1997-2018 Free Software Foundation, Inc.
>> -
>>     This file is part of the GNU C Library.
>>  
>>     The GNU C Library is free software; you can redistribute it and/or
>> @@ -16,55 +15,16 @@
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -#include <errno.h>
>> -#include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> +/* Required for AArch32 compatibility. */
>>  #define SA_RESTORER	0x04000000
>>  
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> -#include <kernel_sigaction.h>
>> -
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int result;
>> -  struct kernel_sigaction kact;
>> -  struct kernel_sigaction koact;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -      kact.sa_flags = act->sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      if (kact.sa_flags & SA_RESTORER)
>> -	kact.sa_restorer = act->sa_restorer;
>> -#endif
>> -    }
>> +#define SET_SA_RESTORER(kact, act)				\
>> + ({								\
>> +    if ((kact)->sa_flags & SA_RESTORER)				\
>> +      (kact)->sa_restorer = (act)->sa_restorer;			\
>> + })
>>  
>> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
>> -			   act ? &kact : NULL,
>> -			   oact ? &koact : NULL, _NSIG / 8);
>> -  if (result >= 0 || errno != ENOSYS)
>> -    {
>> -      if (oact && result >= 0)
>> -	{
>> -	  oact->sa_handler = koact.k_sa_handler;
>> -	  memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -	  oact->sa_flags = koact.sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -	  oact->sa_restorer = koact.sa_restorer;
>> -#endif
>> -	}
>> -    }
>> -  return result;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> +#define RESET_SA_RESTORER(act, kact)				\
>> +  (act)->sa_restorer = (kact)->sa_restorer;
>>  
>> -#include <nptl/sigaction.c>
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>> diff --git a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
>> index 4c35d96..25180ff 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
>> +++ b/sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h
>> @@ -1,15 +1,12 @@
>> -/* This is the sigaction struction from the Linux 2.1.20 kernel.  */
>> +#ifndef _KERNEL_SIGACTION_H
>> +# define _KERNEL_SIGACTION_H
>>  
>> -struct old_kernel_sigaction {
>> -	__sighandler_t k_sa_handler;
>> -	unsigned long sa_mask;
>> -	unsigned int sa_flags;
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction
>> +{
>> +  __sighandler_t k_sa_handler;
>> +  unsigned int sa_flags;
>> +  sigset_t sa_mask;
>>  };
>>  
>> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
>> -
>> -struct kernel_sigaction {
>> -	__sighandler_t k_sa_handler;
>> -	unsigned int sa_flags;
>> -	sigset_t sa_mask;
>> -};
>> +#endif
>> diff --git a/sysdeps/unix/sysv/linux/arm/sigaction.c b/sysdeps/unix/sysv/linux/arm/sigaction.c
>> index e4d80de..c828250 100644
>> --- a/sysdeps/unix/sysv/linux/arm/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/arm/sigaction.c
>> @@ -15,70 +15,25 @@
>>     License along with the GNU C Library.  If not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -#include <errno.h>
>> -#include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> -#include <kernel_sigaction.h>
>> -
>>  #define SA_RESTORER	0x04000000
>>  
>>  extern void __default_sa_restorer (void);
>>  extern void __default_rt_sa_restorer (void);
>>  
>> -/* When RT signals are in use we need to use a different return stub.  */
>> -#define choose_restorer(flags)					\
>> -  (flags & SA_SIGINFO) ? __default_rt_sa_restorer		\
>> -  : __default_sa_restorer
>> -
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int result;
>> -
>> -  struct kernel_sigaction kact, koact;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -      kact.sa_flags = act->sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      if (kact.sa_flags & SA_RESTORER)
>> -	kact.sa_restorer = act->sa_restorer;
>> -      else
>> -	{
>> -	  kact.sa_restorer = choose_restorer (kact.sa_flags);
>> -	  kact.sa_flags |= SA_RESTORER;
>> -	}
>> -#endif
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
>> -			   act ? &kact : NULL,
>> -			   oact ? &koact : NULL, _NSIG / 8);
>> -
>> -  if (oact && result >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      oact->sa_restorer = koact.sa_restorer;
>> -#endif
>> -    }
>> -  return result;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> +#define SET_SA_RESTORER(kact, act)				\
>> + ({								\
>> +   if ((kact)->sa_flags & SA_RESTORER)				\
>> +     (kact)->sa_restorer = (act)->sa_restorer;			\
>> +   else								\
>> +     {								\
>> +       (kact)->sa_restorer = ((kact)->sa_flags & SA_SIGINFO)	\
>> +			     ? __default_rt_sa_restorer		\
>> +			     : __default_sa_restorer;		\
>> +       (kact)->sa_flags |= SA_RESTORER;				\
>> +     }								\
>> + })
>> +
>> +#define RESET_SA_RESTORER(act, kact)				\
>> +  (act)->sa_restorer = (kact)->sa_restorer;
>> +
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>> diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
>> index a5eb9e0..137c73b 100644
>> --- a/sysdeps/unix/sysv/linux/i386/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
>> @@ -16,78 +16,28 @@
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -#include <sysdep.h>
>> -#include <errno.h>
>> -#include <stddef.h>
>>  #include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>>  #include <ldsodefs.h>
>>  
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> -#include <kernel_sigaction.h>
>> -
>> -/* We do not globally define the SA_RESTORER flag so do it here.  */
>>  #define SA_RESTORER 0x04000000
>>  
>> -
>> -/* Using the hidden attribute here does not change the code but it
>> -   helps to avoid warnings.  */
>> -#ifdef __NR_rt_sigaction
>>  extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
>> -#endif
>>  extern void restore (void) asm ("__restore") attribute_hidden;
>>  
>> +#define SET_SA_RESTORER(kact, act)				\
>> +  ({								\
>> +     if (GLRO(dl_sysinfo_dso) == NULL)				\
>> +       {							\
>> +	 (kact)->sa_flags |= SA_RESTORER;			\
>> +         (kact)->sa_restorer = (((act)->sa_flags & SA_SIGINFO)	\
>> +			       ? &restore_rt : &restore);	\
>> +       }							\
>> +  })
>>  
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int result;
>> -
>> -  struct kernel_sigaction kact, koact;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      kact.sa_flags = act->sa_flags;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -
>> -      if (GLRO(dl_sysinfo_dso) == NULL)
>> -	{
>> -	  kact.sa_flags |= SA_RESTORER;
>> -
>> -	  kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
>> -			      ? &restore_rt : &restore);
>> -	}
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  INTERNAL_SYSCALL_DECL (err);
>> -  result = INTERNAL_SYSCALL (rt_sigaction, err, 4,
>> -			     sig, act ? &kact : NULL,
>> -			     oact ? &koact : NULL, _NSIG / 8);
>> -  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
>> -     return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
>> -								       err));
>> -  else if (oact && result >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -      oact->sa_restorer = koact.sa_restorer;
>> -    }
>> -  return result;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> +#define RESET_SA_RESTORER(act, kact) \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>>  
>> -#include <nptl/sigaction.c>
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>>  
>>  /* NOTE: Please think twice before making any changes to the bits of
>>     code below.  GDB needs some intimate knowledge about it to
>> @@ -108,10 +58,8 @@ asm						\
>>     "	int  $0x80"				\
>>     );
>>  
>> -#ifdef __NR_rt_sigaction
>>  /* The return code for realtime-signals.  */
>>  RESTORE (restore_rt, __NR_rt_sigreturn)
>> -#endif
>>  
>>  /* For the boring old signals.  */
>>  #undef RESTORE2
>> diff --git a/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..05813db
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/ia64/kernel_sigaction.h
>> @@ -0,0 +1,6 @@
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction {
>> +        __sighandler_t k_sa_handler;
>> +        unsigned long sa_flags;
>> +        sigset_t sa_mask;               /* mask last for extensibility */
>> +};
>> diff --git a/sysdeps/unix/sysv/linux/ia64/sigaction.c b/sysdeps/unix/sysv/linux/ia64/sigaction.c
>> deleted file mode 100644
>> index e7fb8cd..0000000
>> --- a/sysdeps/unix/sysv/linux/ia64/sigaction.c
>> +++ /dev/null
>> @@ -1,45 +0,0 @@
>> -/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
>> -   This file is part of the GNU C Library.
>> -   Linux/IA64 specific sigaction
>> -   Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
>> -
>> -   The GNU C Library is free software; you can redistribute it and/or
>> -   modify it under the terms of the GNU Lesser General Public
>> -   License as published by the Free Software Foundation; either
>> -   version 2.1 of the License, or (at your option) any later version.
>> -
>> -   The GNU C Library is distributed in the hope that it will be useful,
>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> -   Lesser General Public License for more details.
>> -
>> -   You should have received a copy of the GNU Lesser General Public
>> -   License along with the GNU C Library; if not, see
>> -   <http://www.gnu.org/licenses/>.  */
>> -
>> -/* Linux/ia64 only has rt signals, thus we do not even want to try falling
>> -   back to the old style signals as the default Linux handler does. */
>> -
>> -#include <errno.h>
>> -#include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> -/* The variable is shared between all wrappers around signal handling
>> -   functions which have RT equivalents.  This is the definition.  */
>> -
>> -
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> diff --git a/sysdeps/unix/sysv/linux/kernel_sigaction.h b/sysdeps/unix/sysv/linux/kernel_sigaction.h
>> index d005cbc..2dbec08 100644
>> --- a/sysdeps/unix/sysv/linux/kernel_sigaction.h
>> +++ b/sysdeps/unix/sysv/linux/kernel_sigaction.h
>> @@ -1,19 +1,20 @@
>> -/* This is the sigaction structure from the Linux 2.1.20 kernel.  */
>> +#ifndef _KERNEL_SIGACTION_H
>> +# define _KERNEL_SIGACTION_H
>>  
>> -#define HAVE_SA_RESTORER
>> -
>> -struct old_kernel_sigaction {
>> -	__sighandler_t k_sa_handler;
>> -	unsigned long sa_mask;
>> -	unsigned long sa_flags;
>> -	void (*sa_restorer) (void);
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction
>> +{
>> +  __sighandler_t k_sa_handler;
>> +  unsigned long sa_flags;
>> +#ifdef SA_RESTORER
>> +  void (*sa_restorer) (void);
>> +#endif
>> +  sigset_t sa_mask;
>>  };
>>  
>> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
>> +#ifndef SA_RESTORER
>> +# define SET_SA_RESTORER(kact, act)
>> +# define RESET_SA_RESTORER(act, kact)
>> +#endif
>>  
>> -struct kernel_sigaction {
>> -	__sighandler_t k_sa_handler;
>> -	unsigned long sa_flags;
>> -	void (*sa_restorer) (void);
>> -	sigset_t sa_mask;
>> -};
>> +#endif
>> diff --git a/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..54972fe
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
>> @@ -0,0 +1,22 @@
>> +#ifndef _KERNEL_SIGACTION_H
>> +# define _KERNEL_SIGACTION_H
>> +
>> +#include <signal.h>
>> +
>> +#define SA_RESTORER 0x04000000
>> +
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction
>> +{
>> +  __sighandler_t k_sa_handler;
>> +  sigset_t sa_mask;
>> +  unsigned long sa_flags;
>> +  void (*sa_restorer) (void);
>> +};
>> +
>> +#define SET_SA_RESTORER(kact, act)			\
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)			\
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> +
>> +#endif
>> diff --git a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
>> index b6f52cc..beef976 100644
>> --- a/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
>> +++ b/sysdeps/unix/sysv/linux/mips/kernel_sigaction.h
>> @@ -1,40 +1,12 @@
>> -/* This is the sigaction structure from the Linux 2.1.24 kernel.  */
>> -
>> -#include <sgidefs.h>
>> -
>> -#define HAVE_SA_RESTORER
>> -
>> -struct old_kernel_sigaction {
>> -	unsigned int	sa_flags;
>> -	__sighandler_t	k_sa_handler;
>> -	unsigned long	sa_mask;
>> -	unsigned int    __pad0[3]; /* reserved, keep size constant */
>> -
>> -	/* Abi says here follows reserved int[2] */
>> -	void		(*sa_restorer)(void);
>> -#if (_MIPS_SZPTR < 64)
>> -	/*
>> -	 * For 32 bit code we have to pad struct sigaction to get
>> -	 * constant size for the ABI
>> -	 */
>> -	int		pad1[1]; /* reserved */
>> -#endif
>> +#ifndef _KERNEL_SIGACTION_H
>> +# define _KERNEL_SIGACTION_H
>> +
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction
>> +{
>> +  unsigned int    sa_flags;
>> +  __sighandler_t  k_sa_handler;
>> +  sigset_t        sa_mask;
>>  };
>>  
>> -
>> -#define _KERNEL_NSIG	       128
>> -#define _KERNEL_NSIG_BPW       _MIPS_SZLONG
>> -#define _KERNEL_NSIG_WORDS     (_KERNEL_NSIG / _KERNEL_NSIG_BPW)
>> -
>> -typedef struct {
>> -	unsigned long sig[_KERNEL_NSIG_WORDS];
>> -} kernel_sigset_t;
>> -
>> -/* This is the sigaction structure from the Linux 2.1.68 kernel.  */
>> -struct kernel_sigaction {
>> -	unsigned int	sa_flags;
>> -	__sighandler_t	k_sa_handler;
>> -	kernel_sigset_t	sa_mask;
>> -	void		(*sa_restorer)(void);
>> -	int		s_resv[1]; /* reserved */
>> -};
>> +#endif
>> diff --git a/sysdeps/unix/sysv/linux/mips/sigaction.c b/sysdeps/unix/sysv/linux/mips/sigaction.c
>> deleted file mode 100644
>> index 008b688..0000000
>> --- a/sysdeps/unix/sysv/linux/mips/sigaction.c
>> +++ /dev/null
>> @@ -1,116 +0,0 @@
>> -/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
>> -   This file is part of the GNU C Library.
>> -
>> -   The GNU C Library is free software; you can redistribute it and/or
>> -   modify it under the terms of the GNU Lesser General Public
>> -   License as published by the Free Software Foundation; either
>> -   version 2.1 of the License, or (at your option) any later version.
>> -
>> -   The GNU C Library is distributed in the hope that it will be useful,
>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> -   Lesser General Public License for more details.
>> -
>> -   You should have received a copy of the GNU Lesser General Public
>> -   License along with the GNU C Library.  If not, see
>> -   <http://www.gnu.org/licenses/>.  */
>> -
>> -#include <errno.h>
>> -#include <sgidefs.h>
>> -#include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> -#include <sgidefs.h>
>> -
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> -#include <kernel_sigaction.h>
>> -
>> -#if _MIPS_SIM != _ABIO32
>> -
>> -# ifdef __NR_rt_sigreturn
>> -static void restore_rt (void) asm ("__restore_rt");
>> -# endif
>> -# ifdef __NR_sigreturn
>> -static void restore (void) asm ("__restore");
>> -# endif
>> -#endif
>> -
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int result;
>> -
>> -  struct kernel_sigaction kact, koact;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kernel_sigset_t));
>> -      kact.sa_flags = act->sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -# if _MIPS_SIM == _ABIO32
>> -      kact.sa_restorer = act->sa_restorer;
>> -# else
>> -      kact.sa_restorer = &restore_rt;
>> -# endif
>> -#endif
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.	*/
>> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
>> -			   act ? &kact : NULL,
>> -			   oact ? &koact : NULL,
>> -			   sizeof (kernel_sigset_t));
>> -
>> -  if (oact && result >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask,
>> -	      sizeof (kernel_sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      oact->sa_restorer = koact.sa_restorer;
>> -#endif
>> -    }
>> -  return result;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> -
>> -
>> -/* NOTE: Please think twice before making any changes to the bits of
>> -   code below.  GDB needs some intimate knowledge about it to
>> -   recognize them as signal trampolines, and make backtraces through
>> -   signal handlers work right.  Important are both the names
>> -   (__restore_rt) and the exact instruction sequence.
>> -   If you ever feel the need to make any changes, please notify the
>> -   appropriate GDB maintainer.  */
>> -
>> -#define RESTORE(name, syscall) RESTORE2 (name, syscall)
>> -#define RESTORE2(name, syscall) \
>> -asm						\
>> -  (						\
>> -   ".align 4\n"					\
>> -   "__" #name ":\n"				\
>> -   "	li $2, " #syscall "\n"			\
>> -   "	syscall\n"				\
>> -   );
>> -
>> -/* The return code for realtime-signals.  */
>> -#if _MIPS_SIM != _ABIO32
>> -# ifdef __NR_rt_sigreturn
>> -RESTORE (restore_rt, __NR_rt_sigreturn)
>> -# endif
>> -# ifdef __NR_sigreturn
>> -RESTORE (restore, __NR_sigreturn)
>> -# endif
>> -#endif
>> diff --git a/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..4ada322
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
>> @@ -0,0 +1,8 @@
>> +/* NIOS2 uses the generic Linux UAPI but defines SA_RESTORER.  */
>> +#define SA_RESTORER 0x04000000
>> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..c5213f2
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
>> @@ -0,0 +1,8 @@
>> +/* powerpc kernel sigaction is similar to generic Linux UAPI one.  */
>> +#define SA_RESTORER 0x04000000
>> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..a8beaf7
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/s390/kernel_sigaction.h
>> @@ -0,0 +1,28 @@
>> +#include <bits/types/siginfo_t.h>
>> +
>> +#define SA_RESTORER	0x04000000
>> +
>> +/* This is the sigaction structure from the Linux 3.2 kernel.  */
>> +struct kernel_sigaction
>> +{
>> +  union
>> +  {
>> +    __sighandler_t _sa_handler;
>> +    void (*_sa_sigaction)(int, siginfo_t *, void *);
>> +  } _u;
>> +#define k_sa_handler _u._sa_handler
>> +#ifndef __s390x__
>> +  sigset_t sa_mask;
>> +  unsigned long sa_flags;
>> +  void (*sa_restorer)(void);
>> +#else
>> +  unsigned long sa_flags;
>> +  void (*sa_restorer)(void);
>> +  sigset_t sa_mask;
>> +#endif
>> +};
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c b/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
>> deleted file mode 100644
>> index c13927c..0000000
>> --- a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c
>> +++ /dev/null
>> @@ -1,43 +0,0 @@
>> -/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
>> -   This file is part of the GNU C Library.
>> -
>> -   The GNU C Library is free software; you can redistribute it and/or
>> -   modify it under the terms of the GNU Lesser General Public
>> -   License as published by the Free Software Foundation; either
>> -   version 2.1 of the License, or (at your option) any later version.
>> -
>> -   The GNU C Library is distributed in the hope that it will be useful,
>> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> -   Lesser General Public License for more details.
>> -
>> -   You should have received a copy of the GNU Lesser General Public
>> -   License along with the GNU C Library; if not, see
>> -   <http://www.gnu.org/licenses/>.  */
>> -
>> -/* 64 bit Linux for S/390 only has rt signals, thus we do not even want to try
>> -   falling back to the old style signals as the default Linux handler does. */
>> -
>> -#include <errno.h>
>> -#include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> -/* The variable is shared between all wrappers around signal handling
>> -   functions which have RT equivalents.  This is the definition.  */
>> -
>> -
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  return INLINE_SYSCALL (rt_sigaction, 4, sig, act, oact, _NSIG / 8);
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> diff --git a/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..7ebcd08
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
>> @@ -0,0 +1,8 @@
>> +/* SH uses the generic Linux UAPI but defines SA_RESTORER.  */
>> +#define SA_RESTORER 0x04000000
>> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c
>> index 40a311a..0e6851a 100644
>> --- a/sysdeps/unix/sysv/linux/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/sigaction.c
>> @@ -22,11 +22,19 @@
>>  #include <sysdep.h>
>>  #include <sys/syscall.h>
>>  
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> +/* New ports should not define the obsolete SA_RESTORER, however some
>> +   architecture requires for compat mode and/or due old ABI.  */
>>  #include <kernel_sigaction.h>
>>  
>> +#ifndef SA_RESTORER
>> +# define SET_SA_RESTORER(kact, act)
>> +# define RESET_SA_RESTORER(act, kact)
>> +#endif
>> +
>> +/* SPARC passes the restore function as an argument to rt_sigaction.  */
>> +#ifndef STUB
>> +# define STUB(act)
>> +#endif
>>  
>>  /* If ACT is not NULL, change the action for SIG to *ACT.
>>     If OACT is not NULL, put the old action for SIG in *OACT.  */
>> @@ -42,25 +50,21 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>>        kact.k_sa_handler = act->sa_handler;
>>        memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>>        kact.sa_flags = act->sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      kact.sa_restorer = act->sa_restorer;
>> -#endif
>> +      SET_SA_RESTORER (&kact, act);
>>      }
>>  
>>    /* XXX The size argument hopefully will have to be changed to the
>>       real size of the user-level sigset_t.  */
>> -  result = INLINE_SYSCALL (rt_sigaction, 4, sig,
>> -			   act ? &kact : NULL,
>> -			   oact ? &koact : NULL, _NSIG / 8);
>> +  result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
>> +				act ? &kact : NULL,
>> +				oact ? &koact : NULL, STUB(act) _NSIG / 8);
>>  
>>    if (oact && result >= 0)
>>      {
>>        oact->sa_handler = koact.k_sa_handler;
>>        memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>>        oact->sa_flags = koact.sa_flags;
>> -#ifdef HAVE_SA_RESTORER
>> -      oact->sa_restorer = koact.sa_restorer;
>> -#endif
>> +      RESET_SA_RESTORER (oact, &koact);
>>      }
>>    return result;
>>  }
>> diff --git a/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..bee7e9c
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
>> @@ -0,0 +1,10 @@
>> +/* SPARC 'struct __new_sigaction' is similar to generic Linux UAPI with
>> +   a sa_restorer field, even though function is passed as an argument
>> +   to rt_sigaction syscall.  */
>> +#define SA_RESTORER 0x04000000
>> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = NULL
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
>> index 204a5d8..c1d8f45 100644
>> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
>> @@ -27,43 +27,12 @@
>>  static void __rt_sigreturn_stub (void);
>>  static void __sigreturn_stub (void);
>>  
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  struct kernel_sigaction kact, koact;
>> -  unsigned long stub = 0;
>> -  int ret;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -      if (((kact.sa_flags = act->sa_flags) & SA_SIGINFO) != 0)
>> -	stub = (unsigned long) &__rt_sigreturn_stub;
>> -      else
>> -	stub = (unsigned long) &__sigreturn_stub;
>> -      stub -= 8;
>> -      kact.sa_restorer = NULL;
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  ret = INLINE_SYSCALL (rt_sigaction, 5, sig, act ? &kact : 0,
>> -			oact ? &koact : 0, stub, _NSIG / 8);
>> -
>> -  if (oact && ret >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -      oact->sa_restorer = koact.sa_restorer;
>> -    }
>> -  return ret;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> +#define STUB(act) \
>> +  ((unsigned long)((act->sa_flags & SA_SIGINFO)		\
>> +		    ? &__rt_sigreturn_stub		\
>> +		    : &__sigreturn_stub) - 8),
>>  
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>>  
>>  static
>>  inhibit_stack_protector
>> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
>> index 73cda4c..cfbbc6e 100644
>> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
>> @@ -21,50 +21,13 @@
>>  #include <string.h>
>>  #include <syscall.h>
>>  #include <sysdep.h>
>> -#include <sys/signal.h>
>> -#include <errno.h>
>> -
>> -#include <kernel_sigaction.h>
>> -
>> -/* SPARC 64bit userland requires a kernel that has rt signals anyway. */
>>  
>>  static void __rt_sigreturn_stub (void);
>>  
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int ret;
>> -  struct kernel_sigaction kact, koact;
>> -  unsigned long stub = ((unsigned long) &__rt_sigreturn_stub) - 8;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -      kact.sa_flags = act->sa_flags;
>> -      kact.sa_restorer = NULL;
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  ret = INLINE_SYSCALL (rt_sigaction, 5, sig,
>> -			act ? &kact : 0,
>> -			oact ? &koact : 0, stub, _NSIG / 8);
>> -
>> -  if (oact && ret >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -      oact->sa_restorer = koact.sa_restorer;
>> -    }
>> -
>> -  return ret;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> +#define STUB(act) \
>> +  (((unsigned long) &__rt_sigreturn_stub) - 8),
>>  
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>>  
>>  static
>>  inhibit_stack_protector
>> diff --git a/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
>> new file mode 100644
>> index 0000000..a943d52
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/tile/kernel_sigaction.h
>> @@ -0,0 +1,9 @@
>> +/* tile kernel sigaction is similar to generic Linux UAPI one
>> +   and SA_RESTORER is used only for binary compatibility.  */
>> +#define SA_RESTORER 0x04000000
>> +#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
>> +
>> +#define SET_SA_RESTORER(kact, act)             \
>> +  (kact)->sa_restorer = (act)->sa_restorer
>> +#define RESET_SA_RESTORER(act, kact)           \
>> +  (act)->sa_restorer = (kact)->sa_restorer
>> diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
>> index 2f7459f..4e6d9cc 100644
>> --- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c
>> +++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
>> @@ -16,65 +16,20 @@
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -#include <sysdep.h>
>> -#include <errno.h>
>> -#include <stddef.h>
>>  #include <signal.h>
>> -#include <string.h>
>> -
>> -#include <sysdep.h>
>> -#include <sys/syscall.h>
>> -
>> -/* The difference here is that the sigaction structure used in the
>> -   kernel is not the same as we use in the libc.  Therefore we must
>> -   translate it here.  */
>> -#include <kernel_sigaction.h>
>> -
>> -#include "ucontext_i.h"
>> -
>> -/* We do not globally define the SA_RESTORER flag so do it here.  */
>>  #define SA_RESTORER 0x04000000
>> +#include <kernel_sigaction.h>
>>  
>> -/* Using the hidden attribute here does not change the code but it
>> -   helps to avoid warnings.  */
>>  extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
>>  
>> +#define SET_SA_RESTORER(kact, act)			\
>> +  (kact)->sa_flags = (act)->sa_flags | SA_RESTORER;	\
>> +  (kact)->sa_restorer = &restore_rt
>>  
>> -/* If ACT is not NULL, change the action for SIG to *ACT.
>> -   If OACT is not NULL, put the old action for SIG in *OACT.  */
>> -int
>> -__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>> -{
>> -  int result;
>> -  struct kernel_sigaction kact, koact;
>> -
>> -  if (act)
>> -    {
>> -      kact.k_sa_handler = act->sa_handler;
>> -      memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
>> -      kact.sa_flags = act->sa_flags | SA_RESTORER;
>> -
>> -      kact.sa_restorer = &restore_rt;
>> -    }
>> -
>> -  /* XXX The size argument hopefully will have to be changed to the
>> -     real size of the user-level sigset_t.  */
>> -  result = INLINE_SYSCALL (rt_sigaction, 4,
>> -			   sig, act ? &kact : NULL,
>> -			   oact ? &koact : NULL, _NSIG / 8);
>> -  if (oact && result >= 0)
>> -    {
>> -      oact->sa_handler = koact.k_sa_handler;
>> -      memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
>> -      oact->sa_flags = koact.sa_flags;
>> -      oact->sa_restorer = koact.sa_restorer;
>> -    }
>> -  return result;
>> -}
>> -libc_hidden_def (__libc_sigaction)
>> -
>> -#include <nptl/sigaction.c>
>> +#define RESET_SA_RESTORER(act, kact) 			\
>> +  (act)->sa_restorer = (kact)->sa_restorer
>>  
>> +#include <sysdeps/unix/sysv/linux/sigaction.c>
>>  
>>  /* NOTE: Please think twice before making any changes to the bits of
>>     code below.  GDB needs some intimate knowledge about it to
>> @@ -93,6 +48,8 @@ libc_hidden_def (__libc_sigaction)
>>     a bit tricky.  We don't use the gas cfi directives, so that we can
>>     reliably add .cfi_signal_frame.  */
>>  
>> +#include "ucontext_i.h"
>> +
>>  #define do_cfa_expr						\
>>    "	.byte 0x0f\n"		/* DW_CFA_def_cfa_expression */	\
>>    "	.uleb128 2f-1f\n"	/* length */			\
>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-04-05 18:23 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-12 12:42 [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
2018-02-12 12:49 ` [PATCH v4 2/4] Filter out NPTL internal signals (BZ #22391) Adhemerval Zanella
2018-02-19 17:51   ` Adhemerval Zanella
2018-04-03 14:24     ` Adhemerval Zanella
2018-04-03 15:12       ` Zack Weinberg
2018-04-03 16:14         ` Adhemerval Zanella
2018-02-12 12:53 ` [PATCH v4 3/4] linux: Consolidate sigaction implementation Adhemerval Zanella
2018-02-19 17:54   ` Adhemerval Zanella
2018-04-05 18:23     ` Adhemerval Zanella
2018-02-12 14:02 ` [PATCH v4 4/4] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) Adhemerval Zanella
2018-02-19 18:08   ` Adhemerval Zanella
2018-02-19 18:23   ` H.J. Lu
2018-02-19 17:51 ` [PATCH v4 1/4] Rename nptl-signals.h to internal-signals.h Adhemerval Zanella
2018-02-20 13:00 ` Florian Weimer
2018-02-20 13:45   ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).