Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2
3#define _GNU_SOURCE
4#include <signal.h>
5#include <stdio.h>
6#include <stdbool.h>
7#include <string.h>
8#include <err.h>
9#include <errno.h>
10#include <limits.h>
11#include <sys/mman.h>
12#include <sys/auxv.h>
13#include <sys/prctl.h>
14#include <sys/resource.h>
15#include <setjmp.h>
16
17#include "helpers.h"
18
19/* sigaltstack()-enforced minimum stack */
20#define ENFORCED_MINSIGSTKSZ 2048
21
22#ifndef AT_MINSIGSTKSZ
23# define AT_MINSIGSTKSZ 51
24#endif
25
26static int nerrs;
27
28static bool sigalrm_expected;
29
30static unsigned long at_minstack_size;
31
32static int setup_altstack(void *start, unsigned long size)
33{
34 stack_t ss;
35
36 memset(&ss, 0, sizeof(ss));
37 ss.ss_size = size;
38 ss.ss_sp = start;
39
40 return sigaltstack(&ss, NULL);
41}
42
43static jmp_buf jmpbuf;
44
45static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
46{
47 if (sigalrm_expected) {
48 printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");
49 nerrs++;
50 } else {
51 printf("[OK]\tSIGSEGV signal delivered.\n");
52 }
53
54 siglongjmp(jmpbuf, 1);
55}
56
57static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
58{
59 if (!sigalrm_expected) {
60 printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");
61 nerrs++;
62 } else {
63 printf("[OK]\tSIGALRM signal delivered.\n");
64 }
65}
66
67static void test_sigaltstack(void *altstack, unsigned long size)
68{
69 if (setup_altstack(altstack, size))
70 err(1, "sigaltstack()");
71
72 sigalrm_expected = (size > at_minstack_size) ? true : false;
73
74 sethandler(SIGSEGV, sigsegv, 0);
75 sethandler(SIGALRM, sigalrm, SA_ONSTACK);
76
77 if (!sigsetjmp(jmpbuf, 1)) {
78 printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",
79 sigalrm_expected ? "" : "in");
80 printf("\tRaise SIGALRM. %s is expected to be delivered.\n",
81 sigalrm_expected ? "It" : "SIGSEGV");
82 raise(SIGALRM);
83 }
84
85 clearhandler(SIGALRM);
86 clearhandler(SIGSEGV);
87}
88
89int main(void)
90{
91 void *altstack;
92
93 at_minstack_size = getauxval(AT_MINSIGSTKSZ);
94
95 altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
96 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
97 if (altstack == MAP_FAILED)
98 err(1, "mmap()");
99
100 if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
101 test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
102
103 test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
104
105 return nerrs == 0 ? 0 : 1;
106}