]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/helpers/data_exec.c
15 #define ALT_STK_SIZE (MINSIGSTKSZ + pagesize)
17 #if __i386__ || __ppc__
18 typedef unsigned int psint_t
;
20 #if __x86_64__ || __ppc64__
21 typedef unsigned long long psint_t
;
26 #define msg(...) do { if (verbose) printf(__VA_ARGS__); } while (0);
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.
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.
38 #define HEAP_PROT_EXEC 1
40 #define STACK_PROT_EXEC 3
43 #define FAIL -1 /* can't use 0 since setjmp uses that */
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 */
53 FAIL
, /* execute from heap */
54 SUCCEED
, /* exeucte from heap with PROT_EXEC */
55 FAIL
, /* execute from stack */
56 SUCCEED
, /* exeucte from stack with PROT_EXEC */
59 SUCCEED
, /* execute from heap */
60 SUCCEED
, /* exeucte from heap with PROT_EXEC */
61 SUCCEED
, /* execute from stack */
62 SUCCEED
, /* exeucte from stack with PROT_EXEC */
65 FAIL
, /* execute from heap */
66 SUCCEED
, /* exeucte from heap with PROT_EXEC */
67 FAIL
, /* execute from stack */
68 SUCCEED
, /* exeucte from stack with PROT_EXEC */
73 main(int argc
, char *argv
[])
77 char buf
[func_len
+ 4];
83 struct sigaction sigact
;
89 while ((c
= getopt(argc
, argv
, "v")) != -1) {
97 fprintf(stderr
, "usage: data_exec [-v]\n");
102 pagesize
= getpagesize();
104 sigstk
.ss_sp
= malloc(ALT_STK_SIZE
);
105 sigstk
.ss_size
= ALT_STK_SIZE
;
108 if (sigaltstack(&sigstk
, NULL
) < 0) {
109 perror("sigaltstack");
113 sigact
.sa_handler
= catch_segv
;
114 sigact
.sa_flags
= SA_ONSTACK
;
115 sigemptyset(&sigact
.sa_mask
);
117 if (sigaction(SIGSEGV
, &sigact
, NULL
) == -1) {
118 perror("sigaction SIGSEGV");
122 if (sigaction(SIGBUS
, &sigact
, NULL
) == -1) {
123 perror("sigaction SIGBUS");
131 if ((result
= setjmp(resume
)) != 0) {
132 if (result
!= expected
[test
]) {
133 printf("%s: test %d failed, expected %d, got %d\n", cmd_name
, test
, expected
[test
], result
);
143 msg("attempting to execute from malloc'ed area..\n");
145 func
= (void *)malloc(func_len
);
147 func
= (void *)((char *)func
+ ((psint_t
)test_func
& 0x3));
149 bcopy(test_func
, func
, func_len
);
152 msg("execution suceeded, result is %d\n\n", result
);
153 longjmp(resume
, SUCCEED
);
156 msg("attempting to execute from malloc'ed area with PROT_EXEC..\n");
158 func
= (void *)malloc(func_len
);
160 func
= (void *)((char *)func
+ ((psint_t
)test_func
& 0x3));
161 bcopy(test_func
, func
, func_len
);
163 base
= (psint_t
)func
& ~(pagesize
- 1);
164 len
= func_len
+ (psint_t
)func
- base
;
166 if(mprotect((void *)base
, len
, PROT_READ
|PROT_WRITE
|PROT_EXEC
) == -1) {
167 perror("mprotect of stack");
172 msg("execution suceeded, result is %d\n\n", result
);
173 longjmp(resume
, SUCCEED
);
176 msg("attempting to execute from stack...\n");
178 func
= (void *)(buf
+ ((psint_t
)test_func
& 0x3));
179 bcopy(test_func
, func
, func_len
);
182 msg("stack execution suceeded, result from stack exec is %d\n\n", result
);
183 longjmp(resume
, SUCCEED
);
185 case STACK_PROT_EXEC
:
186 msg("attempting to execute from stack with PROT_EXEC...\n");
188 func
= (void *)(buf
+ ((psint_t
)test_func
& 0x3));
189 bcopy(test_func
, func
, func_len
);
191 base
= (psint_t
)func
& ~(pagesize
- 1);
192 len
= func_len
+ (psint_t
)func
- base
;
194 if(mprotect((void *)base
, len
, PROT_READ
|PROT_WRITE
|PROT_EXEC
) == -1) {
195 perror("mprotect of stack");
200 msg("stack execution suceeded, result from stack exec is %d\n", result
);
201 longjmp(resume
, SUCCEED
);
204 msg("All tests passed.\n");
219 msg("got sig %d\n\n", sig
);
220 longjmp(resume
, FAIL
);