[PATCH 11/17] x86/cet: Sync with Linux kernel 6.6 shadow stack interface

szabolcs.nagy@arm.com szabolcs.nagy@arm.com
Tue Dec 19 17:15:50 GMT 2023


The 12/18/2023 11:06, H.J. Lu wrote:
> On Mon, Dec 18, 2023 at 2:54 AM szabolcs.nagy@arm.com
> <szabolcs.nagy@arm.com> wrote:
> > it does if it scans.
> >
> > for (;; targetssp--) {
> >   if (targetssp == ssp) do_samestack();
> >   if (*targetssp == restoretoken) do_differentstack();
> > }
> >
> > the only problem i see is if the target shadow stack is
> > different from the current one and does not end in a restore
> > token. but i think that is a user error.
> 
> Yes, it works.  But it is hard to tell its performance overhead.
> 
> > if we plan to introduce altshadowstack then this does not
> > work in case of shadow stack overflow because the overflowed
> > shadow stack cannot be jumped to even though in practice we
> > want that to work.
> >
> 
> I'd like to support shadow stack in glibc 2.39.  Since my patch
> doesn't enable shadow stack by default, it doesn't have any
> functionality impact on users.  It allows us to evaluate shadow
> stack support in all packages.  We may need to use WRUSS
> to enable shadow stack for some packages.  But users and
> developers can't see how shadow stack works if shadow stack
> can't be turned on.

ok.

> From 3dba6d876db6a47b66a680bb4aa85b1db63aa3f8 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Wed, 13 Dec 2023 17:50:47 -0800
> Subject: [PATCH] x86-64/cet: Check the restore token in longjmp
> 
> setcontext and swapcontext put a restore token on the old shadow stack
> so that they switch to a different shadow stack when switching user
> contexts.  When longjmp from a user context, the target shadow stack
> can be different from the current shadow stack and INCSSP can't be
> used to restore the shadow stack pointer to the target shadow stack.
> Update longjmp to search for a restore token.  If found, use the token
> to restore the shadow stack pointer before using INCSSP to pop the
> shadow stack.  Stop the token search and use INCSSP if the shadow stack
> entry value is the same as the current shadow stack pointer.
> 
> It is a user error if there is a shadow stack switch without leaving a
> restore token on the old shadow stack.

looks good except missing saveprevssp below

> ---
>  sysdeps/x86_64/__longjmp.S | 28 +++++++++++++++++++++++++++-
>  1 file changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
> index 9ac075e0a8..b106affdcd 100644
> --- a/sysdeps/x86_64/__longjmp.S
> +++ b/sysdeps/x86_64/__longjmp.S
> @@ -63,9 +63,35 @@ ENTRY(__longjmp)
>  	/* Check and adjust the Shadow-Stack-Pointer.  */
>  	/* Get the current ssp.  */
>  	rdsspq %rax
> +	/* Save the current ssp.  */
> +	movq %rax, %r10
>  	/* And compare it with the saved ssp value.  */
> -	subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> +	movq SHADOW_STACK_POINTER_OFFSET(%rdi), %rcx
> +	subq %rcx, %rax
>  	je L(skip_ssp)
> +
> +L(find_restore_token_loop):
> +	/* Look for a restore token.  */
> +	movq -8(%rcx), %rbx
> +	andq $-8, %rbx
> +	cmpq %rcx, %rbx
> +	/* Find the restore token.  */
> +	je L(restore_shadow_stack)
> +
> +	/* Try the next slot.  */
> +	subq $8, %rcx
> +	/* Stop if the current ssp is found.  */
> +	cmpq %rcx, %r10
> +	je L(no_shadow_stack_token)
> +	jmp L(find_restore_token_loop)
> +
> +L(restore_shadow_stack):
> +	/* Restore the target shadow stack.  */
> +	rstorssp -8(%rcx)
> +	rdsspq %rax
> +	subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> +

i'd use saveprevssp in this case so the old shadow stack
remains resumable with a later longjmp.

> +L(no_shadow_stack_token):
>  	/* Count the number of frames to adjust and adjust it
>  	   with incssp instruction.  The instruction can adjust
>  	   the ssp by [0..255] value only thus use a loop if
> -- 
> 2.43.0
> 



More information about the Libc-alpha mailing list