public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: "H.J. Lu" <hjl.tools@gmail.com>
To: Noah Goldstein <goldstein.w.n@gmail.com>
Cc: libc-alpha@sourceware.org, rick.p.edgecombe@intel.com
Subject: Re: [PATCH] x86-64/cet: Check the restore token in longjmp
Date: Thu, 4 Jan 2024 11:22:56 -0800	[thread overview]
Message-ID: <CAMe9rOq+s_P3aKAmTOi3H8SBzmboA7RMdRfGdoYsryQm9XqKuQ@mail.gmail.com> (raw)
In-Reply-To: <CAFUsyfJ_BrCwZqXcvD5zW1tYyY42Qrc2G2ZtUJEz3BUFFB8=3g@mail.gmail.com>

On Thu, Jan 4, 2024 at 11:12 AM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> On Tue, Jan 2, 2024 at 6:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, Jan 1, 2024 at 10:03 AM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
> > >
> > > On Mon, Jan 1, 2024 at 6:03 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > setcontext and swapcontext put a restore token on the old shadow stack
> > > > which is used to restore the target 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.
> > > > ---
> > > >  .../unix/sysv/linux/x86_64/____longjmp_chk.S  | 30 ++++++++++++++++++-
> > > >  sysdeps/x86_64/__longjmp.S                    | 30 ++++++++++++++++++-
> > > >  2 files changed, 58 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> > > > index 1b735bbbb2..855c934218 100644
> > > > --- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> > > > +++ b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> > > > @@ -121,9 +121,37 @@ ENTRY(____longjmp_chk)
> > > >  # endif
> > > >         /* Check and adjust the Shadow-Stack-Pointer.  */
> > > >         rdsspq  %rax
> > > > +       /* Save the current ssp.  */
> > > > +       movq    %rax, %r10
> > > > +       movq    SHADOW_STACK_POINTER_OFFSET(%rdi), %rcx
> > > >         /* And compare it with the saved ssp value.  */
> > > > -       subq    SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> > > > +       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)
> > > > +       /* Save the restore token on the old shadow stack.  */
> > > > +       saveprevssp
> > > > +       rdsspq  %rax
> > > > +       subq    SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> > > > +
> > > > +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
> > > > diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
> > > > index 9ac075e0a8..4f449115e6 100644
> > > > --- a/sysdeps/x86_64/__longjmp.S
> > > > +++ b/sysdeps/x86_64/__longjmp.S
> > > > @@ -63,9 +63,37 @@ 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
> > > cmpq?
> >
> > %rax is used at L(no_shadow_stack_token):
> >          negq %rax
> >
> > which is the difference between the current ssp and the target
> > ssp.
> >
> > > >         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)
> > > jne  L(find_restore_token_loop)
> > > jmp L(no_shadow_stack_token)
> > > to save a branch in the loop itself.
> >
> > Fixed in v2.
> >
> > > > +
> > > > +L(restore_shadow_stack):
> > > > +       /* Restore the target shadow stack.  */
> > > > +       rstorssp -8(%rcx)
> > >
> > > Does this not need to be the aligned address?
> >
> > Shadow stack is always 8-byte aligned.
>
> If thats the case, can you use `rbx` instead of `-8(%rcx)` here?
> Also do you need the `and $-8, %rbx`?

The restore token has a special format.

This “Shadow stack restore token” is a 64-bit value formatted as follows:
 • Bit 63:2 – 4-byte aligned SSP for which this restore point was created.
   This SSP must be at an address that is 8 or 12 byte above the address
   where this token itself is found. The RSTORSSP instruction verifies
this property.
• Bit 1 – reserved. Must be zero
• Bit 0 – Mode bit. If 0 then this shadow stack restore token can be used
  by RSTORSSP instruction in 32-bit mode.    If 1 then this shadow stack
  restore token can be used by the RSTORSSP   instruction in 64-bit mode.

`and $-8, %rbx` will mark out the lower 8-bit bits before comparison
against the current SSP.

> >
> > > > +       /* Save the restore token on the old shadow stack.  */
> > > > +       saveprevssp
> > > > +       rdsspq %rax
> > > > +       subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> > >
> > > maybe cache `SHADOW_STACK_POINTER_OFFSET(%rdi)` in some
> > > free register above?
> >
> > Fixed in v2.
> >
> > > > +
> > > > +L(no_shadow_stack_token):
> > > Looks like duplicate between __longjmp.S and __longjmp_chk.S.
> > > Can we either 1) make these functions or 2) define them as a macro
> > > to be included by both?
> >
> > Fixed in v2.
> >
> > > >         /* 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
> > > >
> >
> > Thanks.
> >
> > --
> > H.J.



-- 
H.J.

      reply	other threads:[~2024-01-04 19:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-01 14:03 H.J. Lu
2024-01-01 18:02 ` Noah Goldstein
2024-01-02 14:30   ` H.J. Lu
2024-01-04 19:12     ` Noah Goldstein
2024-01-04 19:22       ` H.J. Lu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMe9rOq+s_P3aKAmTOi3H8SBzmboA7RMdRfGdoYsryQm9XqKuQ@mail.gmail.com \
    --to=hjl.tools@gmail.com \
    --cc=goldstein.w.n@gmail.com \
    --cc=libc-alpha@sourceware.org \
    --cc=rick.p.edgecombe@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).