]> git.saurik.com Git - apple/xnu.git/blame - tools/tests/xnu_quick_test/helpers/data_exec.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / helpers / data_exec.c
CommitLineData
b0d623f7
A
1#include <stdio.h>
2#include <strings.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <signal.h>
6#include <setjmp.h>
7#include <sys/mman.h>
8
9int test_func();
10void catch_segv(int);
11jmp_buf resume;
12
13#define func_len 256
14
15#define ALT_STK_SIZE (MINSIGSTKSZ + pagesize)
16
6d2010ae 17#if __i386__
b0d623f7
A
18typedef unsigned int psint_t;
19#endif
6d2010ae 20#if __x86_64__
b0d623f7
A
21typedef unsigned long long psint_t;
22#endif
23
24int verbose = 0;
25
26#define msg(...) do { if (verbose) printf(__VA_ARGS__); } while (0);
27
28/*
29 * Test whether the architecture allows execution from the stack and heap data areas. What's
30 * allowed varies by architecture due to backwards compatibility. We also run a separate test
31 * where we turn on PROT_EXEC explicitly which should always allow execution to take place.
32 *
33 * The "expected" array tells us what the result of each test should be based on the architecture.
34 * The code assumes the test numbers in the macros below are consecutive starting from 0.
35 */
36
37#define HEAP_TEST 0
38#define HEAP_PROT_EXEC 1
39#define STACK_TEST 2
40#define STACK_PROT_EXEC 3
41
42#define SUCCEED 1
43#define FAIL -1 /* can't use 0 since setjmp uses that */
44
45int expected[4] = {
6d2010ae 46#if NXDATA32TESTNONX
b0d623f7
A
47 SUCCEED, /* execute from heap */
48 SUCCEED, /* exeucte from heap with PROT_EXEC */
49 FAIL, /* execute from stack */
50 SUCCEED, /* exeucte from stack with PROT_EXEC */
6d2010ae
A
51#elif __i386__
52 FAIL, /* execute from heap */
b0d623f7
A
53 SUCCEED, /* exeucte from heap with PROT_EXEC */
54 FAIL, /* execute from stack */
55 SUCCEED, /* exeucte from stack with PROT_EXEC */
56#endif
6d2010ae 57#if __x86_64__
b0d623f7
A
58 FAIL, /* execute from heap */
59 SUCCEED, /* exeucte from heap with PROT_EXEC */
60 FAIL, /* execute from stack */
61 SUCCEED, /* exeucte from stack with PROT_EXEC */
62#endif
63};
64
65
66main(int argc, char *argv[])
67{
68 int (*func)();
69 int result, test;
70 char buf[func_len + 4];
71 psint_t base;
72 unsigned int len;
73 psint_t pagesize;
74 size_t count;
75 stack_t sigstk;
76 struct sigaction sigact;
77 char *cmd_name;
78 int c;
79
80 cmd_name = argv[0];
81
82 while ((c = getopt(argc, argv, "v")) != -1) {
83 switch (c) {
84 case 'v':
85 verbose = 1;
86 break;
87
88 case '?':
89 default:
90 fprintf(stderr, "usage: data_exec [-v]\n");
91 exit(1);
92 }
93 }
94
95 pagesize = getpagesize();
96
97 sigstk.ss_sp = malloc(ALT_STK_SIZE);
98 sigstk.ss_size = ALT_STK_SIZE;
99 sigstk.ss_flags = 0;
100
101 if (sigaltstack(&sigstk, NULL) < 0) {
102 perror("sigaltstack");
103 exit(1);
104 }
105
106 sigact.sa_handler = catch_segv;
107 sigact.sa_flags = SA_ONSTACK;
108 sigemptyset(&sigact.sa_mask);
109
110 if (sigaction(SIGSEGV, &sigact, NULL) == -1) {
111 perror("sigaction SIGSEGV");
112 exit(1);
113 }
114
115 if (sigaction(SIGBUS, &sigact, NULL) == -1) {
116 perror("sigaction SIGBUS");
117 exit(1);
118 }
119
120 test = HEAP_TEST;
121
122restart:
123
124 if ((result = setjmp(resume)) != 0) {
125 if (result != expected[test]) {
126 printf("%s: test %d failed, expected %d, got %d\n", cmd_name, test, expected[test], result);
127 exit(2);
128 }
129
130 test++;
131 goto restart;
132 }
133
134 switch (test) {
135 case HEAP_TEST:
136 msg("attempting to execute from malloc'ed area..\n");
137
138 func = (void *)malloc(func_len);
139
140 func = (void *)((char *)func + ((psint_t)test_func & 0x3));
141
142 bcopy(test_func, func, func_len);
143
144 result = (*func)();
145 msg("execution suceeded, result is %d\n\n", result);
146 longjmp(resume, SUCCEED);
147
148 case HEAP_PROT_EXEC:
149 msg("attempting to execute from malloc'ed area with PROT_EXEC..\n");
150
151 func = (void *)malloc(func_len);
152
153 func = (void *)((char *)func + ((psint_t)test_func & 0x3));
154 bcopy(test_func, func, func_len);
155
156 base = (psint_t)func & ~(pagesize - 1);
157 len = func_len + (psint_t)func - base;
158
159 if(mprotect((void *)base, len, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
160 perror("mprotect of stack");
161 exit(1);
162 }
163
164 result = (*func)();
165 msg("execution suceeded, result is %d\n\n", result);
166 longjmp(resume, SUCCEED);
167
168 case STACK_TEST:
169 msg("attempting to execute from stack...\n");
170
171 func = (void *)(buf + ((psint_t)test_func & 0x3));
172 bcopy(test_func, func, func_len);
173
174 result = (*func)();
175 msg("stack execution suceeded, result from stack exec is %d\n\n", result);
176 longjmp(resume, SUCCEED);
177
178 case STACK_PROT_EXEC:
179 msg("attempting to execute from stack with PROT_EXEC...\n");
180
181 func = (void *)(buf + ((psint_t)test_func & 0x3));
182 bcopy(test_func, func, func_len);
183
184 base = (psint_t)func & ~(pagesize - 1);
185 len = func_len + (psint_t)func - base;
186
187 if(mprotect((void *)base, len, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
188 perror("mprotect of stack");
189 exit(1);
190 }
191
192 result = (*func)();
193 msg("stack execution suceeded, result from stack exec is %d\n", result);
194 longjmp(resume, SUCCEED);
195 }
196
197 msg("All tests passed.\n");
198 exit(0);
199}
200
201
202int
203test_func()
204{
205 return 42;
206}
207
208
209void
210catch_segv(int sig)
211{
212 msg("got sig %d\n\n", sig);
213 longjmp(resume, FAIL);
214}