1 // SPDX-License-Identifier: GPL-2.0-only
13 #include <sys/prctl.h>
14 #include <sys/resource.h>
17 /* sigaltstack()-enforced minimum stack */
18 #define ENFORCED_MINSIGSTKSZ 2048
20 #ifndef AT_MINSIGSTKSZ
21 # define AT_MINSIGSTKSZ 51
26 static bool sigalrm_expected;
28 static unsigned long at_minstack_size;
30 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
35 memset(&sa, 0, sizeof(sa));
36 sa.sa_sigaction = handler;
37 sa.sa_flags = SA_SIGINFO | flags;
38 sigemptyset(&sa.sa_mask);
39 if (sigaction(sig, &sa, 0))
43 static void clearhandler(int sig)
47 memset(&sa, 0, sizeof(sa));
48 sa.sa_handler = SIG_DFL;
49 sigemptyset(&sa.sa_mask);
50 if (sigaction(sig, &sa, 0))
54 static int setup_altstack(void *start, unsigned long size)
58 memset(&ss, 0, sizeof(ss));
62 return sigaltstack(&ss, NULL);
65 static jmp_buf jmpbuf;
67 static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
69 if (sigalrm_expected) {
70 printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");
73 printf("[OK]\tSIGSEGV signal delivered.\n");
76 siglongjmp(jmpbuf, 1);
79 static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
81 if (!sigalrm_expected) {
82 printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");
85 printf("[OK]\tSIGALRM signal delivered.\n");
89 static void test_sigaltstack(void *altstack, unsigned long size)
91 if (setup_altstack(altstack, size))
92 err(1, "sigaltstack()");
94 sigalrm_expected = (size > at_minstack_size) ? true : false;
96 sethandler(SIGSEGV, sigsegv, 0);
97 sethandler(SIGALRM, sigalrm, SA_ONSTACK);
99 if (!sigsetjmp(jmpbuf, 1)) {
100 printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",
101 sigalrm_expected ? "" : "in");
102 printf("\tRaise SIGALRM. %s is expected to be delivered.\n",
103 sigalrm_expected ? "It" : "SIGSEGV");
107 clearhandler(SIGALRM);
108 clearhandler(SIGSEGV);
115 at_minstack_size = getauxval(AT_MINSIGSTKSZ);
117 altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
118 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
119 if (altstack == MAP_FAILED)
122 if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
123 test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
125 test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
127 return nerrs == 0 ? 0 : 1;