Browse Source
Validate stack switching and recursion depth. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20251008215613.300150-74-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>pull/305/head
committed by
Peter Maydell
3 changed files with 84 additions and 1 deletions
@ -0,0 +1,74 @@ |
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|||
|
|||
#include "gcs.h" |
|||
|
|||
#define IN_PROGRESS(X) ((uint64_t)(X) | 5) |
|||
#define CAP(X) (((uint64_t)(X) & ~0xfff) + 1) |
|||
|
|||
static uint64_t * __attribute__((noinline)) recurse(size_t index) |
|||
{ |
|||
if (index == 0) { |
|||
return gcspr(); |
|||
} |
|||
return recurse(index - 1); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
void *tmp; |
|||
uint64_t *alt_stack, *alt_cap; |
|||
uint64_t *orig_pr, *orig_cap; |
|||
uint64_t *bottom; |
|||
size_t pagesize = getpagesize(); |
|||
size_t words; |
|||
|
|||
enable_gcs(0); |
|||
orig_pr = gcspr(); |
|||
|
|||
/* Allocate a guard page before and after. */ |
|||
tmp = mmap(0, 3 * pagesize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); |
|||
assert(tmp != MAP_FAILED); |
|||
|
|||
/* map_shadow_stack won't replace existing mappings */ |
|||
munmap(tmp + pagesize, pagesize); |
|||
|
|||
/* Allocate a new stack between the guards. */ |
|||
alt_stack = (uint64_t *) |
|||
syscall(__NR_map_shadow_stack, tmp + pagesize, pagesize, |
|||
SHADOW_STACK_SET_TOKEN); |
|||
assert(alt_stack == tmp + pagesize); |
|||
|
|||
words = pagesize / 8; |
|||
alt_cap = alt_stack + words - 1; |
|||
|
|||
/* SHADOW_STACK_SET_TOKEN set the cap. */ |
|||
assert(*alt_cap == CAP(alt_cap)); |
|||
|
|||
/* Swap to the alt stack, one step at a time. */ |
|||
gcsss1(alt_cap); |
|||
|
|||
assert(gcspr() == alt_cap); |
|||
assert(*alt_cap == IN_PROGRESS(orig_pr)); |
|||
|
|||
orig_cap = gcsss2(); |
|||
|
|||
assert(orig_cap == orig_pr - 1); |
|||
assert(*orig_cap == CAP(orig_cap)); |
|||
assert(gcspr() == alt_stack + words); |
|||
|
|||
/* We should be able to use the whole stack. */ |
|||
bottom = recurse(words - 1); |
|||
assert(bottom == alt_stack); |
|||
|
|||
/* We should be back where we started. */ |
|||
assert(gcspr() == alt_stack + words); |
|||
|
|||
/* Swap back to the original stack. */ |
|||
gcsss1(orig_cap); |
|||
tmp = gcsss2(); |
|||
|
|||
assert(gcspr() == orig_pr); |
|||
assert(tmp == alt_cap); |
|||
|
|||
exit(0); |
|||
} |
|||
Loading…
Reference in new issue