57da8bfde60b5e406c99f8c8b20a5411ce464d0e
[deliverable/linux.git] / tools / testing / selftests / sigaltstack / sas.c
1 /*
2 * Stas Sergeev <stsp@users.sourceforge.net>
3 *
4 * test sigaltstack(SS_ONSTACK | SS_AUTODISARM)
5 * If that succeeds, then swapcontext() can be used inside sighandler safely.
6 *
7 */
8
9 #define _GNU_SOURCE
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/mman.h>
14 #include <ucontext.h>
15 #include <alloca.h>
16 #include <string.h>
17 #include <assert.h>
18
19 #ifndef SS_AUTODISARM
20 #define SS_AUTODISARM (1 << 4)
21 #endif
22
23 static void *sstack, *ustack;
24 static ucontext_t uc, sc;
25 static const char *msg = "[OK]\tStack preserved";
26 static const char *msg2 = "[FAIL]\tStack corrupted";
27 struct stk_data {
28 char msg[128];
29 int flag;
30 };
31
32 void my_usr1(int sig, siginfo_t *si, void *u)
33 {
34 char *aa;
35 int err;
36 stack_t stk;
37 struct stk_data *p;
38
39 register unsigned long sp asm("sp");
40
41 if (sp < (unsigned long)sstack ||
42 sp >= (unsigned long)sstack + SIGSTKSZ) {
43 printf("[FAIL]\tSP is not on sigaltstack\n");
44 exit(EXIT_FAILURE);
45 }
46 /* put some data on stack. other sighandler will try to overwrite it */
47 aa = alloca(1024);
48 assert(aa);
49 p = (struct stk_data *)(aa + 512);
50 strcpy(p->msg, msg);
51 p->flag = 1;
52 printf("[RUN]\tsignal USR1\n");
53 err = sigaltstack(NULL, &stk);
54 if (err) {
55 perror("[FAIL]\tsigaltstack()");
56 exit(EXIT_FAILURE);
57 }
58 if (stk.ss_flags != SS_DISABLE)
59 printf("[FAIL]\tss_flags=%i, should be SS_DISABLE\n",
60 stk.ss_flags);
61 else
62 printf("[OK]\tsigaltstack is disabled in sighandler\n");
63 swapcontext(&sc, &uc);
64 printf("%s\n", p->msg);
65 if (!p->flag) {
66 printf("[RUN]\tAborting\n");
67 exit(EXIT_FAILURE);
68 }
69 }
70
71 void my_usr2(int sig, siginfo_t *si, void *u)
72 {
73 char *aa;
74 struct stk_data *p;
75
76 printf("[RUN]\tsignal USR2\n");
77 aa = alloca(1024);
78 /* dont run valgrind on this */
79 /* try to find the data stored by previous sighandler */
80 p = memmem(aa, 1024, msg, strlen(msg));
81 if (p) {
82 printf("[FAIL]\tsigaltstack re-used\n");
83 /* corrupt the data */
84 strcpy(p->msg, msg2);
85 /* tell other sighandler that his data is corrupted */
86 p->flag = 0;
87 }
88 }
89
90 static void switch_fn(void)
91 {
92 printf("[RUN]\tswitched to user ctx\n");
93 raise(SIGUSR2);
94 setcontext(&sc);
95 }
96
97 int main(void)
98 {
99 struct sigaction act;
100 stack_t stk;
101 int err;
102
103 sigemptyset(&act.sa_mask);
104 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
105 act.sa_sigaction = my_usr1;
106 sigaction(SIGUSR1, &act, NULL);
107 act.sa_sigaction = my_usr2;
108 sigaction(SIGUSR2, &act, NULL);
109 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
110 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
111 if (sstack == MAP_FAILED) {
112 perror("mmap()");
113 return EXIT_FAILURE;
114 }
115 stk.ss_sp = sstack;
116 stk.ss_size = SIGSTKSZ;
117 stk.ss_flags = SS_ONSTACK | SS_AUTODISARM;
118 err = sigaltstack(&stk, NULL);
119 if (err) {
120 perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)");
121 stk.ss_flags = SS_ONSTACK;
122 }
123 err = sigaltstack(&stk, NULL);
124 if (err) {
125 perror("[FAIL]\tsigaltstack(SS_ONSTACK)");
126 return EXIT_FAILURE;
127 }
128
129 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
130 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
131 if (ustack == MAP_FAILED) {
132 perror("mmap()");
133 return EXIT_FAILURE;
134 }
135 getcontext(&uc);
136 uc.uc_link = NULL;
137 uc.uc_stack.ss_sp = ustack;
138 uc.uc_stack.ss_size = SIGSTKSZ;
139 makecontext(&uc, switch_fn, 0);
140 raise(SIGUSR1);
141
142 err = sigaltstack(NULL, &stk);
143 if (err) {
144 perror("[FAIL]\tsigaltstack()");
145 exit(EXIT_FAILURE);
146 }
147 if (stk.ss_flags != 0) {
148 printf("[FAIL]\tss_flags=%i, should be 0\n",
149 stk.ss_flags);
150 exit(EXIT_FAILURE);
151 }
152 printf("[OK]\tsigaltstack is enabled after signal\n");
153
154 printf("[OK]\tTest passed\n");
155 return 0;
156 }
This page took 0.046062 seconds and 4 git commands to generate.