]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
S/390: Fix setcontext/swapcontext which are not restoring sigmask. [BZ #18080]
authorStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 28 Apr 2016 08:12:05 +0000 (10:12 +0200)
committerStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 28 Apr 2016 08:12:05 +0000 (10:12 +0200)
This patch uses sigprocmask(SIG_SETMASK) instead of SIG_BLOCK
in setcontext, swapcontext.

(cherry picked from commit 2e807f29595eb5b1e5d0decc6e356a3562ecc58e)

ChangeLog
NEWS
stdlib/Makefile
stdlib/tst-setcontext2.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S

index 685dd909f2ac3cca32f6897954212fee82f1b80a..9b6e9f54e0a679fbc2f24abc3042fa72a294bcff 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2016-04-28  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #18080]
+       * sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
+       (__setcontext): Use SIG_SETMASK instead of SIG_BLOCK.
+       * sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
+       (__setcontext): Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
+       (__swapcontext): Use SIG_SETMASK instead of SIG_BLOCK.
+       Call rt_sigprocmask syscall one time to set new signal mask
+       and retrieve the current signal mask instead of two calls.
+       * sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
+       (__swapcontext): Likewise.
+       * stdlib/Makefile (tests): Add new testcase tst-setcontext2.
+       * stdlib/tst-setcontext2.c: New file.
+
 2016-04-01  Florian Weimer  <fweimer@redhat.com>
 
        [BZ #19879]
diff --git a/NEWS b/NEWS
index d7da53f9ba2f30f7e34e575c6b4bb6818cf21e0b..18d873e4b8d9c881c3b26d62b27ef9c350a9f24a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,7 @@ Version 2.19.1
   15946, 16545, 16574, 16623, 16657, 16695, 16743, 16758, 16759, 16760,
   16878, 16882, 16885, 16916, 16932, 16943, 16958, 17048, 17062, 17069,
   17079, 17137, 17153, 17213, 17263, 17269, 17325, 17555, 17905, 18007,
-  18032, 18240, 18287, 18905, 19879.
+  18032, 18080, 18240, 18287, 18905, 19879.
 
 * A buffer overflow in gethostbyname_r and related functions performing DNS
   requests has been fixed.  If the NSS functions were called with a
index 1be16eb8d0b5098a988023213ff0bc57ea9b465e..b46c4a1fea9d1171ab57499f6a1b25449f3b07ed 100644 (file)
@@ -64,11 +64,11 @@ test-srcs   := tst-fmtmsg
 tests          := tst-strtol tst-strtod testmb testrand testsort testdiv   \
                   test-canon test-canon2 tst-strtoll tst-environ           \
                   tst-xpg-basename tst-random tst-random2 tst-bsearch      \
-                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
-                  test-a64l tst-qsort tst-system testmb2 bug-strtod2       \
-                  tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
-                  tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2       \
-                  tst-makecontext2 tst-strtod6 tst-unsetenv1               \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+                  tst-setcontext2 test-a64l tst-qsort tst-system testmb2   \
+                  bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3  \
+                  tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5     \
+                  tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1    \
                   tst-makecontext3 bug-getcontext bug-fmtmsg1              \
                   tst-secure-getenv tst-strtod-overflow tst-strtod-round   \
                   tst-tininess tst-strtod-underflow tst-tls-atexit
diff --git a/stdlib/tst-setcontext2.c b/stdlib/tst-setcontext2.c
new file mode 100644 (file)
index 0000000..8582cc0
--- /dev/null
@@ -0,0 +1,230 @@
+/* Testcase checks, if setcontext(), swapcontext() restores signal-mask
+   and if pending signals are delivered after those calls.
+   Copyright (C) 2015 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+volatile int global;
+volatile sig_atomic_t handlerCalled;
+
+static void
+check (const char *funcName)
+{
+  sigset_t set;
+
+  /* check if SIGUSR2 is unblocked after setcontext-call.  */
+  sigprocmask (SIG_BLOCK, NULL, &set);
+
+  if (sigismember (&set, SIGUSR2) != 0)
+    {
+      printf ("FAIL: SIGUSR2 is blocked after %s.\n", funcName);
+      exit (1);
+    }
+
+  if (sigismember (&set, SIGUSR1) != 1)
+    {
+      printf ("FAIL: SIGUSR1 is not blocked after %s.\n", funcName);
+      exit (1);
+    }
+}
+
+static void
+signalmask (int how, int signum)
+{
+  sigset_t set;
+  sigemptyset (&set);
+  sigaddset (&set, signum);
+  if (sigprocmask (how, &set, NULL) != 0)
+    {
+      printf ("FAIL: sigprocmaks (%d, %d, NULL): %m\n", how, signum);
+      exit (1);
+    }
+}
+
+static void
+signalpending (int signum, const char *msg)
+{
+  sigset_t set;
+  sigemptyset (&set);
+  if (sigpending (&set) != 0)
+    {
+      printf ("FAIL: sigpending: %m\n");
+      exit (1);
+    }
+  if (sigismember (&set, SIGUSR2) != 1)
+    {
+      printf ("FAIL: Signal %d is not pending %s\n", signum, msg);
+      exit (1);
+    }
+}
+
+static void
+handler (int __attribute__ ((unused)) signum)
+{
+  handlerCalled ++;
+}
+
+static int
+do_test (void)
+{
+  ucontext_t ctx, oldctx;
+  struct sigaction action;
+  pid_t pid;
+
+  pid = getpid ();
+
+  /* unblock SIGUSR2 */
+  signalmask (SIG_UNBLOCK, SIGUSR2);
+
+  /* block SIGUSR1 */
+  signalmask (SIG_BLOCK, SIGUSR1);
+
+  /* register handler for SIGUSR2  */
+  action.sa_flags = 0;
+  action.sa_handler = handler;
+  sigemptyset (&action.sa_mask);
+  sigaction (SIGUSR2, &action, NULL);
+
+  if (getcontext (&ctx) != 0)
+    {
+      printf ("FAIL: getcontext: %m\n");
+      exit (1);
+    }
+
+  global++;
+
+  if (global == 1)
+    {
+      puts ("after getcontext");
+
+      /* block SIGUSR2  */
+      signalmask (SIG_BLOCK, SIGUSR2);
+
+      /* send SIGUSR2 to me  */
+      handlerCalled = 0;
+      kill (pid, SIGUSR2);
+
+      /* was SIGUSR2 handler called?  */
+      if (handlerCalled != 0)
+       {
+         puts ("FAIL: signal handler was called, but signal was blocked.");
+         exit (1);
+       }
+
+      /* is SIGUSR2 pending?  */
+      signalpending (SIGUSR2, "before setcontext");
+
+      /* SIGUSR2 will be unblocked by setcontext-call.  */
+      if (setcontext (&ctx) != 0)
+       {
+         printf ("FAIL: setcontext: %m\n");
+         exit (1);
+       }
+    }
+  else if (global == 2)
+    {
+      puts ("after setcontext");
+
+      /* check SIGUSR1/2  */
+      check ("setcontext");
+
+      /* was SIGUSR2 handler called? */
+      if (handlerCalled != 1)
+       {
+         puts ("FAIL: signal handler was not called after setcontext.");
+         exit (1);
+       }
+
+      /* block SIGUSR2 */
+      signalmask (SIG_BLOCK, SIGUSR2);
+
+      /* send SIGUSR2 to me  */
+      handlerCalled = 0;
+      kill (pid, SIGUSR2);
+
+      /* was SIGUSR2 handler called?  */
+      if (handlerCalled != 0)
+       {
+         puts ("FAIL: signal handler was called, but signal was blocked.");
+         exit (1);
+       }
+
+      /* is SIGUSR2 pending?  */
+      signalpending (SIGUSR2, "before swapcontext");
+
+      if (swapcontext (&oldctx, &ctx) != 0)
+       {
+         printf ("FAIL: swapcontext: %m\n");
+         exit (1);
+       }
+
+      puts ("after returned from swapcontext");
+
+      if (global != 3)
+       {
+         puts ("FAIL: returned from swapcontext without ctx-context called.");
+         exit (1);
+       }
+
+      puts ("test succeeded");
+      return 0;
+    }
+  else if ( global != 3 )
+    {
+      puts ("FAIL: 'global' not incremented three times");
+      exit (1);
+    }
+
+  puts ("after swapcontext");
+  /* check SIGUSR1/2  */
+  check ("swapcontext");
+
+  /* was SIGUSR2 handler called? */
+  if (handlerCalled != 1)
+    {
+      puts ("FAIL: signal handler was not called after swapcontext.");
+      exit (1);
+    }
+
+  /* check sigmask in old context of swapcontext-call  */
+  if (sigismember (&oldctx.uc_sigmask, SIGUSR2) != 1)
+    {
+      puts ("FAIL: SIGUSR2 is not blocked in oldctx.uc_sigmask.");
+      exit (1);
+    }
+
+  if (sigismember (&oldctx.uc_sigmask, SIGUSR1) != 1)
+    {
+      puts ("FAIL: SIGUSR1 is not blocked in oldctx.uc_sigmaks.");
+      exit (1);
+    }
+
+  /* change to old context, which was gathered by swapcontext() call.  */
+  setcontext (&oldctx);
+
+  puts ("FAIL: returned from setcontext (&oldctx)");
+  exit (1);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
index 42839e26f16a684ad6fc1ef476c58beeef8e55fb..b26377398ac173ffb939ed1779b64880940696db 100644 (file)
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
        lr      %r1,%r2
 
        /* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
-       la      %r2,SIG_BLOCK
+       la      %r2,SIG_SETMASK
        la      %r3,SC_MASK(%r1)
        slr     %r4,%r4
        lhi     %r5,_NSIG8
index 9206aa334d865bcfd09997bc85d3cfb73aa72877..8f9cfd834d39a466e51d4469764c1b40eca89058 100644 (file)
@@ -24,7 +24,7 @@
 /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
 
   Saves the machine context in oucp such that when it is activated,
-  it appears as if __swapcontextt() returned again, restores the
+  it appears as if __swapcontext() returned again, restores the
   machine context in ucp and thereby resumes execution in that
   context.
 
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
        lr      %r1,%r2
        lr      %r0,%r3
 
-       /* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
-       la      %r2,SIG_BLOCK
-       slr     %r3,%r3
-       la      %r4,SC_MASK(%r1)
-       lhi     %r5,_NSIG8
-       svc     SYS_ify(rt_sigprocmask)
-
        /* Store fpu context.  */
        stfpc   SC_FPC(%r1)
        std     %f0,SC_FPRS(%r1)
@@ -74,11 +67,12 @@ ENTRY(__swapcontext)
        /* Store general purpose registers.  */
        stm     %r0,%r15,SC_GPRS(%r1)
 
-       /* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-       la      %r2,SIG_BLOCK
+       /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+          sigsetsize).  */
+       la      %r2,SIG_SETMASK
        lr      %r5,%r0
        la      %r3,SC_MASK(%r5)
-       slr     %r4,%r4
+       la      %r4,SC_MASK(%r1)
        lhi     %r5,_NSIG8
        svc     SYS_ify(rt_sigprocmask)
 
index 83df5ce461e6b9154818c58a2aa024e9b5addf63..1464e6a0942046bf62a9692b7a8a29e83c1a7fef 100644 (file)
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
        lgr     %r1,%r2
 
        /* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-       la      %r2,SIG_BLOCK
+       la      %r2,SIG_SETMASK
        la      %r3,SC_MASK(%r1)
        slgr    %r4,%r4
        lghi    %r5,_NSIG8
index e3e624c91b6b7bdb2457a110905bd9a0d12c9fc3..8346fd5dd1fc65e729e9ec40b92d4b1cd54178a3 100644 (file)
@@ -24,7 +24,7 @@
 /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
 
   Saves the machine context in oucp such that when it is activated,
-  it appears as if __swapcontextt() returned again, restores the
+  it appears as if __swapcontext() returned again, restores the
   machine context in ucp and thereby resumes execution in that
   context.
 
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
        lgr     %r1,%r2
        lgr     %r0,%r3
 
-       /* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
-       la      %r2,SIG_BLOCK
-       slgr    %r3,%r3
-       la      %r4,SC_MASK(%r1)
-       lghi    %r5,_NSIG8
-       svc     SYS_ify(rt_sigprocmask)
-
        /* Store fpu context.  */
        stfpc   SC_FPC(%r1)
        std     %f0,SC_FPRS(%r1)
@@ -74,12 +67,13 @@ ENTRY(__swapcontext)
        /* Store general purpose registers.  */
        stmg    %r0,%r15,SC_GPRS(%r1)
 
-       /* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
-       la      %r2,SIG_BLOCK
+       /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+          sigsetsize).  */
+       la      %r2,SIG_SETMASK
        lgr     %r5,%r0
        la      %r3,SC_MASK(%r5)
+       la      %r4,SC_MASK(%r1)
        lghi    %r5,_NSIG8
-       slgr    %r4,%r4
        svc     SYS_ify(rt_sigprocmask)
 
        /* Load fpu context.  */