Re: [RFC PATCH 3/5] selftest/x86: Fix sigreturn_64 test.

From: Kees Cook
Date: Thu May 21 2020 - 18:47:20 EST


On Thu, May 21, 2020 at 02:17:18PM -0700, Yu-cheng Yu wrote:
> 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 <yu-cheng.yu@xxxxxxxxx>
> ---
> 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__

I think this should also be gated by whether the compiler will know what
to do with the shadow stack instructions. (Perhaps the earlier Makefile
define can be exported and tested here.)

> + /* 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

--
Kees Cook