aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Sergeev <stsp@list.ru>2016-04-14 16:20:05 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-03 02:37:59 -0400
commit19fd2868e3671b446b13d135a44363182bbd319a (patch)
treeebacbd848577213edf32798ecdd96c362cf03fa0
parent2a74213838104a41588d86fd5e8d344972891ace (diff)
selftests/sigaltstack: Add new testcase for sigaltstack(SS_ONSTACK|SS_AUTODISARM)
This patch adds the test case for SS_AUTODISARM flag. The test-case tries to set SS_AUTODISARM flag and checks if the nested signal corrupts the stack after swapcontext(). Signed-off-by: Stas Sergeev <stsp@list.ru> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shuah Khan <shuahkh@osg.samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-api@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1460665206-13646-5-git-send-email-stsp@list.ru Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/sigaltstack/Makefile8
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c156
3 files changed, 165 insertions, 0 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index b04afc3295df..ff9e5f20a5a7 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -19,6 +19,7 @@ TARGETS += powerpc
19TARGETS += pstore 19TARGETS += pstore
20TARGETS += ptrace 20TARGETS += ptrace
21TARGETS += seccomp 21TARGETS += seccomp
22TARGETS += sigaltstack
22TARGETS += size 23TARGETS += size
23TARGETS += static_keys 24TARGETS += static_keys
24TARGETS += sysctl 25TARGETS += sysctl
diff --git a/tools/testing/selftests/sigaltstack/Makefile b/tools/testing/selftests/sigaltstack/Makefile
new file mode 100644
index 000000000000..56af56eda6fa
--- /dev/null
+++ b/tools/testing/selftests/sigaltstack/Makefile
@@ -0,0 +1,8 @@
1CFLAGS = -Wall
2BINARIES = sas
3all: $(BINARIES)
4
5include ../lib.mk
6
7clean:
8 rm -rf $(BINARIES)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
new file mode 100644
index 000000000000..57da8bfde60b
--- /dev/null
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -0,0 +1,156 @@
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
23static void *sstack, *ustack;
24static ucontext_t uc, sc;
25static const char *msg = "[OK]\tStack preserved";
26static const char *msg2 = "[FAIL]\tStack corrupted";
27struct stk_data {
28 char msg[128];
29 int flag;
30};
31
32void 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
71void 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
90static void switch_fn(void)
91{
92 printf("[RUN]\tswitched to user ctx\n");
93 raise(SIGUSR2);
94 setcontext(&sc);
95}
96
97int 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}