[kvm-unit-tests PATCH v3 10/17] x86: cet: Make shadow stack less fragile

Sean Christopherson
2025-11-14T00:13:18Z

From: Mathias Krause <minipli@grsecurity.net>

The CET shadow stack test has certain assumptions about the code, namely
that it was compiled with frame pointers enabled and the return address
won't be 0xdeaddead.

Make the code less fragile by actually lifting these assumptions to (1)
explicitly mention the dependency to the frame pointer by making us of
__builtin_frame_address(0) and (2) modify the return address by toggling
bits instead of writing a fixed value. Also ensure that write will
actually be generated by the compiler by making it a 'volatile' write.

Signed-off-by: Mathias Krause <minipli@grsecurity.net>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
x86/cet.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/x86/cet.c b/x86/cet.c
index 80864fb1..61059ef2 100644
--- a/x86/cet.c
+++ b/x86/cet.c
@@ -10,14 +10,14 @@

static uint64_t cet_shstk_func(void)
{
- unsigned long *ret_addr, *ssp;
+ unsigned long *ret_addr = __builtin_frame_address(0) + sizeof(void *);
+ unsigned long *ssp;

/* rdsspq %rax */
asm volatile (".byte 0xf3, 0x48, 0x0f, 0x1e, 0xc8" : "=a"(ssp));

- asm("movq %%rbp,%0" : "=r"(ret_addr));
printf("The return-address in shadow-stack = 0x%lx, in normal stack = 0x%lx\n",
- *ssp, *(ret_addr + 1));
+ *ssp, *ret_addr);

/*
* In below line, it modifies the return address, it'll trigger #CP
@@ -26,7 +26,7 @@ static uint64_t cet_shstk_func(void)
* when HW detects the violation.
*/
printf("Try to temper the return-address, this causes #CP on returning...\n");
- *(ret_addr + 1) = 0xdeaddead;
+ *(volatile unsigned long *)ret_addr ^= 0xdeaddead;

return 0;
}
--
2.52.0.rc1.455.g30608eb744-goog