about summary refs log tree commit diff
path: root/signal
diff options
context:
space:
mode:
Diffstat (limited to 'signal')
-rw-r--r--signal/Makefile5
-rw-r--r--signal/signal.h1
-rw-r--r--signal/tst-minsigstksz-5.c84
3 files changed, 88 insertions, 2 deletions
diff --git a/signal/Makefile b/signal/Makefile
index e89c308889..3d8cab1f50 100644
--- a/signal/Makefile
+++ b/signal/Makefile
@@ -31,7 +31,8 @@ headers := signal.h sys/signal.h \
 	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
 	   bits/types/sigset_t.h bits/types/sigval_t.h \
 	   bits/types/stack_t.h bits/types/struct_sigstack.h \
-	   bits/types/__sigval_t.h bits/signal_ext.h
+	   bits/types/__sigval_t.h bits/signal_ext.h \
+	   bits/sigstksz.h
 
 routines	:= signal raise killpg \
 		   sigaction sigprocmask kill \
@@ -48,7 +49,7 @@ routines	:= signal raise killpg \
 tests		:= tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \
 		   tst-sigwait-eintr tst-sigaction \
 		   tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \
-		   tst-minsigstksz-3a tst-minsigstksz-4 \
+		   tst-minsigstksz-3a tst-minsigstksz-4 tst-minsigstksz-5 \
 		   tst-sigisemptyset
 
 include ../Rules
diff --git a/signal/signal.h b/signal/signal.h
index 6463c98e11..b17203c99c 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -312,6 +312,7 @@ extern int siginterrupt (int __sig, int __interrupt) __THROW
   __attribute_deprecated_msg__ ("Use sigaction with SA_RESTART instead");
 
 # include <bits/sigstack.h>
+# include <bits/sigstksz.h>
 # include <bits/ss_flags.h>
 
 /* Alternate signal handler stack interface.
diff --git a/signal/tst-minsigstksz-5.c b/signal/tst-minsigstksz-5.c
new file mode 100644
index 0000000000..d657d2f4e6
--- /dev/null
+++ b/signal/tst-minsigstksz-5.c
@@ -0,0 +1,84 @@
+/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size.
+   Copyright (C) 2020 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static volatile sig_atomic_t handler_run;
+
+static void
+handler (int signo)
+{
+  /* Clear a bit of on-stack memory.  */
+  volatile char buffer[256];
+  for (size_t i = 0; i < sizeof (buffer); ++i)
+    buffer[i] = 0;
+  handler_run = 1;
+}
+
+int
+do_test (void)
+{
+  size_t stack_buffer_size = 64 * 1024 * 1024;
+  void *stack_buffer = xmalloc (stack_buffer_size);
+  void *stack_end = stack_buffer + stack_buffer_size;
+  memset (stack_buffer, 0xCC, stack_buffer_size);
+
+  void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2;
+  void *stack_top = stack_bottom + MINSIGSTKSZ;
+  stack_t stack =
+    {
+      .ss_sp = stack_bottom,
+      .ss_size = MINSIGSTKSZ,
+    };
+  if (sigaltstack (&stack, NULL) < 0)
+    FAIL_RET ("sigaltstack: %m\n");
+
+  struct sigaction act =
+    {
+      .sa_handler = handler,
+      .sa_flags = SA_ONSTACK,
+    };
+  if (sigaction (SIGUSR1, &act, NULL) < 0)
+    FAIL_RET ("sigaction: %m\n");
+
+  if (kill (getpid (), SIGUSR1) < 0)
+    FAIL_RET ("kill: %m\n");
+
+  if (handler_run != 1)
+    FAIL_RET ("handler did not run\n");
+
+  for (void *p = stack_buffer; p < stack_bottom; ++p)
+    if (*(unsigned char *) p != 0xCC)
+      FAIL_RET ("changed byte %ld bytes below configured stack\n",
+		(long) (stack_bottom - p));
+  for (void *p = stack_top; p < stack_end; ++p)
+    if (*(unsigned char *) p != 0xCC)
+      FAIL_RET ("changed byte %ld bytes above configured stack\n",
+		(long) (p - stack_top));
+
+  free (stack_buffer);
+
+  return 0;
+}
+
+#include <support/test-driver.c>