master
c 74 lines 1.8 KB
Raw
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 #include "gcs.h"
4
5 #define IN_PROGRESS(X) ((uint64_t)(X) | 5)
6 #define CAP(X) (((uint64_t)(X) & ~0xfff) + 1)
7
8 static uint64_t * __attribute__((noinline)) recurse(size_t index)
9 {
10 if (index == 0) {
11 return gcspr();
12 }
13 return recurse(index - 1);
14 }
15
16 int main()
17 {
18 void *tmp;
19 uint64_t *alt_stack, *alt_cap;
20 uint64_t *orig_pr, *orig_cap;
21 uint64_t *bottom;
22 size_t pagesize = getpagesize();
23 size_t words;
24
25 enable_gcs(0);
26 orig_pr = gcspr();
27
28 /* Allocate a guard page before and after. */
29 tmp = mmap(0, 3 * pagesize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
30 assert(tmp != MAP_FAILED);
31
32 /* map_shadow_stack won't replace existing mappings */
33 munmap(tmp + pagesize, pagesize);
34
35 /* Allocate a new stack between the guards. */
36 alt_stack = (uint64_t *)
37 syscall(__NR_map_shadow_stack, tmp + pagesize, pagesize,
38 SHADOW_STACK_SET_TOKEN);
39 assert(alt_stack == tmp + pagesize);
40
41 words = pagesize / 8;
42 alt_cap = alt_stack + words - 1;
43
44 /* SHADOW_STACK_SET_TOKEN set the cap. */
45 assert(*alt_cap == CAP(alt_cap));
46
47 /* Swap to the alt stack, one step at a time. */
48 gcsss1(alt_cap);
49
50 assert(gcspr() == alt_cap);
51 assert(*alt_cap == IN_PROGRESS(orig_pr));
52
53 orig_cap = gcsss2();
54
55 assert(orig_cap == orig_pr - 1);
56 assert(*orig_cap == CAP(orig_cap));
57 assert(gcspr() == alt_stack + words);
58
59 /* We should be able to use the whole stack. */
60 bottom = recurse(words - 1);
61 assert(bottom == alt_stack);
62
63 /* We should be back where we started. */
64 assert(gcspr() == alt_stack + words);
65
66 /* Swap back to the original stack. */
67 gcsss1(orig_cap);
68 tmp = gcsss2();
69
70 assert(gcspr() == orig_pr);
71 assert(tmp == alt_cap);
72
73 exit(0);
74 }