Re: [RFC PATCH 3/5] selftest/x86: Fix sigreturn_64 test.
From: Kees Cook <hidden>
Date: 2020-05-21 22:48:55
Also in:
linux-api, linux-arch, linux-mm, lkml
On Thu, May 21, 2020 at 02:17:18PM -0700, Yu-cheng Yu wrote:
quoted hunk ↗ jump to hunk
When shadow stack is enabled, selftests/x86/sigreturn_64 triggers a fault when doing sigreturn to 32-bit context but the task's shadow stack pointer is above 32-bit address range. Fix it by: - Allocate a small shadow stack below 32-bit address, - Switch to the new shadow stack, - Run tests, - Switch back to the original 64-bit shadow stack. Signed-off-by: Yu-cheng Yu <redacted> --- tools/testing/selftests/x86/sigreturn.c | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+)diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c index 57c4f67f16ef..5bcd74d416ff 100644 --- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c@@ -45,6 +45,14 @@ #include <stdbool.h> #include <sys/ptrace.h> #include <sys/user.h> +#include <x86intrin.h> +#include <asm/prctl.h> +#include <sys/prctl.h> + +#ifdef __x86_64__ +int arch_prctl(int code, unsigned long *addr); +#define ARCH_CET_ALLOC_SHSTK 0x3004 +#endif /* Pull in AR_xyz defines. */ typedef unsigned int u32;@@ -766,6 +774,20 @@ int main() int total_nerrs = 0; unsigned short my_cs, my_ss; +#ifdef __x86_64__ + /* Alloc a shadow stack within 32-bit address range */ + unsigned long arg, ssp_64, ssp_32; + ssp_64 = _get_ssp(); + + if (ssp_64 != 0) { + arg = 0x1001; + arch_prctl(ARCH_CET_ALLOC_SHSTK, &arg); + ssp_32 = arg + 0x1000 - 8; + asm volatile("RSTORSSP (%0)\n":: "r" (ssp_32)); + asm volatile("SAVEPREVSSP"); + } +#endif
If the headers and code are going to be repeated, I would put that in a shared header so they're not copy/pasted between these two tests. -Kees -- Kees Cook