public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Noah Goldstein <goldstein.w.n@gmail.com>
To: "H.J. Lu" <hjl.tools@gmail.com>
Cc: libc-alpha@sourceware.org, rick.p.edgecombe@intel.com
Subject: Re: [PATCH v5 1/6] x86/cet: Sync with Linux kernel 6.6 shadow stack interface
Date: Tue, 26 Dec 2023 16:40:12 -0800	[thread overview]
Message-ID: <CAFUsyfJyzuUD8Z1LV3_5BvtcmjvQSs+7ctLeFzkbJhyJ_60BgQ@mail.gmail.com> (raw)
In-Reply-To: <CAMe9rOpQ+GF+LoxmpjVrOk7hbX7YNg112B+fahygaS1Nrbw5hA@mail.gmail.com>

On Tue, Dec 26, 2023 at 9:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Dec 26, 2023 at 9:38 AM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
> >
> > On Fri, Dec 22, 2023 at 8:58 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > Sync with Linux kernel 6.6 shadow stack interface.  Since only x86-64 is
> > > supported, i386 shadow stack codes are unchanged and CET shouldn't be
> > > enabled for i386.
> > >
> > > 1. When the shadow stack base in TCB is unset, the default shadow stack
> > > is in use.  Use the current shadow stack pointer as the marker for the
> > > default shadow stack. It is used to identify if the current shadow stack
> > > is the same as the target shadow stack when switching ucontexts.  If yes,
> > > INCSSP will be used to unwind shadow stack.  Otherwise, shadow stack
> > > restore token will be used.
> > > 2. Allocate shadow stack with the map_shadow_stack syscall.  Since there
> > > is no function to explicitly release ucontext, there is no place to
> > > release shadow stack allocated by map_shadow_stack in ucontext functions.
> > > Such shadow stacks will be leaked.
> > > 3. Rename arch_prctl CET commands to ARCH_SHSTK_XXX.
> > > 4. Rewrite the CET control functions with the current kernel shadow stack
> > > interface.
> > >
> > > Since CET is no longer enabled by kernel, a separate patch will enable
> > > shadow stack during startup.
> > > ---
> > >  sysdeps/unix/sysv/linux/x86/bits/mman.h       |  5 ++
> > >  sysdeps/unix/sysv/linux/x86/cpu-features.c    | 13 +++--
> > >  sysdeps/unix/sysv/linux/x86/dl-cet.h          | 16 ++++--
> > >  .../unix/sysv/linux/x86/include/asm/prctl.h   | 37 ++++++-------
> > >  .../sysv/linux/x86/tst-cet-setcontext-1.c     | 17 +++---
> > >  sysdeps/unix/sysv/linux/x86_64/Makefile       |  2 +-
> > >  .../unix/sysv/linux/x86_64/__start_context.S  | 38 +++----------
> > >  .../sysv/linux/x86_64/allocate-shadow-stack.c | 55 +++++++++++++++++++
> > >  .../sysv/linux/x86_64/allocate-shadow-stack.h | 24 ++++++++
> > >  sysdeps/unix/sysv/linux/x86_64/getcontext.S   | 30 ++--------
> > >  sysdeps/unix/sysv/linux/x86_64/makecontext.c  | 28 +++++-----
> > >  sysdeps/unix/sysv/linux/x86_64/swapcontext.S  | 22 ++------
> > >  sysdeps/x86/cpu-features.c                    | 15 +++--
> > >  sysdeps/x86/dl-cet.c                          |  2 +-
> > >  sysdeps/x86_64/nptl/tls.h                     |  2 +-
> > >  15 files changed, 173 insertions(+), 133 deletions(-)
> > >  create mode 100644 sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.c
> > >  create mode 100644 sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.h
> > >
> > > diff --git a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h
> > > index 3d356e86a0..232b55a13d 100644
> > > --- a/sysdeps/unix/sysv/linux/x86/bits/mman.h
> > > +++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h
> > > @@ -27,6 +27,11 @@
> > >  #define MAP_32BIT      0x40            /* Only give out 32-bit addresses.  */
> > >  #define MAP_ABOVE4G    0x80            /* Only map above 4GB.  */
> > >
> > > +#ifdef __USE_MISC
> > > +/* Set up a restore token in the newly allocated shadow stack */
> > > +# define SHADOW_STACK_SET_TOKEN 0x1
> > > +#endif
> > > +
> > >  #include <bits/mman-map-flags-generic.h>
> > >
> > >  /* Include generic Linux declarations.  */
> > > diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
> > > index 41e7600668..0e6e2bf855 100644
> > > --- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
> > > +++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
> > > @@ -23,10 +23,15 @@
> > >  static inline int __attribute__ ((always_inline))
> > >  get_cet_status (void)
> > >  {
> > > -  unsigned long long cet_status[3];
> > > -  if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_STATUS, cet_status) == 0)
> > > -    return cet_status[0];
> > > -  return 0;
> > > +  unsigned long long kernel_feature;
> > > +  unsigned int status = 0;
> > > +  if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
> > > +                            &kernel_feature) == 0)
> > > +    {
> > > +      if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
> > > +       status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > > +    }
> > > +  return status;
> > >  }
> > >
> > >  # ifndef SHARED
> > > diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > > index c885bf1323..da220ac627 100644
> > > --- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > > +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > > @@ -21,12 +21,20 @@
> > >  static inline int __attribute__ ((always_inline))
> > >  dl_cet_disable_cet (unsigned int cet_feature)
> > >  {
> > > -  return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_DISABLE,
> > > -                                     cet_feature);
> > > +  if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
> > > +    return -1;
> > > +  long long int kernel_feature = ARCH_SHSTK_SHSTK;
> > > +  return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_DISABLE,
> > > +                                     kernel_feature);
> > >  }
> > >
> > >  static inline int __attribute__ ((always_inline))
> > > -dl_cet_lock_cet (void)
> > > +dl_cet_lock_cet (unsigned int cet_feature)
> > >  {
> > > -  return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_LOCK, 0);
> > > +  if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
> > > +    return -1;
> > > +  /* Lock all SHSTK features.  */
> > > +  long long int kernel_feature = -1;
> > > +  return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_LOCK,
> > > +                                     kernel_feature);
> > >  }
> > > diff --git a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
> > > index 45ad0b052f..2f511321ad 100644
> > > --- a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
> > > +++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
> > > @@ -4,24 +4,19 @@
> > >
> > >  #include_next <asm/prctl.h>
> > >
> > > -#ifndef ARCH_CET_STATUS
> > > -/* CET features:
> > > -   IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT
> > > -   SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
> > > - */
> > > -/* Return CET features in unsigned long long *addr:
> > > -     features: addr[0].
> > > -     shadow stack base address: addr[1].
> > > -     shadow stack size: addr[2].
> > > - */
> > > -# define ARCH_CET_STATUS       0x3001
> > > -/* Disable CET features in unsigned int features.  */
> > > -# define ARCH_CET_DISABLE      0x3002
> > > -/* Lock all CET features.  */
> > > -# define ARCH_CET_LOCK         0x3003
> > > -/* Allocate a new shadow stack with unsigned long long *addr:
> > > -     IN: requested shadow stack size: *addr.
> > > -     OUT: allocated shadow stack address: *addr.
> > > - */
> > > -# define ARCH_CET_ALLOC_SHSTK  0x3004
> > > -#endif /* ARCH_CET_STATUS */
> > > +#ifndef ARCH_SHSTK_ENABLE
> > > +/* Enable SHSTK features in unsigned long int features.  */
> > > +# define ARCH_SHSTK_ENABLE             0x5001
> > > +/* Disable SHSTK features in unsigned long int features.  */
> > > +# define ARCH_SHSTK_DISABLE            0x5002
> > > +/* Lock SHSTK features in unsigned long int features.  */
> > > +# define ARCH_SHSTK_LOCK               0x5003
> > > +/* Unlock SHSTK features in unsigned long int features.  */
> > > +# define ARCH_SHSTK_UNLOCK             0x5004
> > > +/* Return SHSTK features in unsigned long int features.  */
> > > +# define ARCH_SHSTK_STATUS             0x5005
> > > +
> > > +/* ARCH_SHSTK_ features bits */
> > > +# define ARCH_SHSTK_SHSTK              0x1
> > > +# define ARCH_SHSTK_WRSS               0x2
> > > +#endif
> > > diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
> > > index 837a9fd0eb..2ea66c803b 100644
> > > --- a/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
> > > +++ b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
> > > @@ -87,15 +87,14 @@ do_test (void)
> > >    ctx[4].uc_link = &ctx[0];
> > >    makecontext (&ctx[4], (void (*) (void)) f1, 0);
> > >
> > > -  /* NB: When shadow stack is enabled, makecontext calls arch_prctl
> > > -     with ARCH_CET_ALLOC_SHSTK to allocate a new shadow stack which
> > > -     can be unmapped.  The base address and size of the new shadow
> > > -     stack are returned in __ssp[1] and __ssp[2].  makecontext is
> > > -     called for CTX1, CTX3 and CTX4.  But only CTX1 is used.  New
> > > -     shadow stacks are allocated in the order of CTX3, CTX1, CTX4.
> > > -     It is very likely that CTX1's shadow stack is placed between
> > > -     CTX3 and CTX4.  We munmap CTX3's and CTX4's shadow stacks to
> > > -     create gaps above and below CTX1's shadow stack.  We check
> > > +  /* NB: When shadow stack is enabled, makecontext calls map_shadow_stack
> > > +     to allocate a new shadow stack which can be unmapped.  The base
> > > +     address and size of the new shadow stack are returned in __ssp[1]
> > > +     and __ssp[2].  makecontext is called for CTX1, CTX3 and CTX4.  But
> > > +     only CTX1 is used.  New shadow stacks are allocated in the order
> > > +     of CTX3, CTX1, CTX4.  It is very likely that CTX1's shadow stack is
> > > +     placed between CTX3 and CTX4.  We munmap CTX3's and CTX4's shadow
> > > +     stacks to create gaps above and below CTX1's shadow stack.  We check
> > >       that setcontext CTX1 works correctly in this case.  */
> > >    if (_get_ssp () != 0)
> > >      {
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/Makefile b/sysdeps/unix/sysv/linux/x86_64/Makefile
> > > index 5e19202ebf..06b873949e 100644
> > > --- a/sysdeps/unix/sysv/linux/x86_64/Makefile
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/Makefile
> > > @@ -3,7 +3,7 @@ sysdep_routines += ioperm iopl
> > >  endif
> > >
> > >  ifeq ($(subdir),stdlib)
> > > -sysdep_routines += __start_context
> > > +sysdep_routines += __start_context allocate-shadow-stack
> > >  endif
> > >
> > >  ifeq ($(subdir),csu)
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/__start_context.S b/sysdeps/unix/sysv/linux/x86_64/__start_context.S
> > > index f6436dd6bb..ae04203c90 100644
> > > --- a/sysdeps/unix/sysv/linux/x86_64/__start_context.S
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/__start_context.S
> > > @@ -24,20 +24,14 @@
> > >  /* Use CALL to push __start_context onto the new stack as well as the new
> > >     shadow stack.  RDI points to ucontext:
> > >     Incoming:
> > > -     __ssp[0]: The original caller's shadow stack pointer.
> > > -     __ssp[1]: The size of the new shadow stack.
> > > -     __ssp[2]: The size of the new shadow stack.
> > > -   Outgoing:
> > >       __ssp[0]: The new shadow stack pointer.
> > >       __ssp[1]: The base address of the new shadow stack.
> > >       __ssp[2]: The size of the new shadow stack.
> > >   */
> > >
> > >  ENTRY(__push___start_context)
> > > -       /* Save the pointer to ucontext.  */
> > > -       movq    %rdi, %r9
> > >         /* Get the original shadow stack pointer.  */
> > > -       rdsspq  %r8
> > > +       rdsspq  %rcx
> > >         /* Save the original stack pointer.  */
> > >         movq    %rsp, %rdx
> > >         /* Load the top of the new stack into RSI.  */
> > > @@ -45,24 +39,12 @@ ENTRY(__push___start_context)
> > >         /* Add 8 bytes to RSI since CALL will push the 8-byte return
> > >            address onto stack.  */
> > >         leaq    8(%rsi), %rsp
> > > -       /* Allocate the new shadow stack.  The size of the new shadow
> > > -          stack is passed in __ssp[1].  */
> > > -       lea     (oSSP + 8)(%rdi), %RSI_LP
> > > -       movl    $ARCH_CET_ALLOC_SHSTK, %edi
> > > -       movl    $__NR_arch_prctl, %eax
> > > -       /* The new shadow stack base is returned in __ssp[1].  */
> > > -       syscall
> > > -       testq   %rax, %rax
> > > -       jne     L(hlt)          /* This should never happen.  */
> > > -
> > > -       /* Get the size of the new shadow stack.  */
> > > -       movq    8(%rsi), %rdi
> > > -
> > > -       /* Get the base address of the new shadow stack.  */
> > > -       movq    (%rsi), %rsi
> > > -
> > > +       /* The size of the new shadow stack is stored in __ssp[2].  */
> > > +       mov     (oSSP + 16)(%rdi), %RSI_LP
> > > +       /* The new shadow stack base is stored in __ssp[1].  */
> > > +       mov     (oSSP + 8)(%rdi), %RAX_LP
> > >         /* Use the restore stoken to restore the new shadow stack.  */
> > > -       rstorssp -8(%rsi, %rdi)
> > > +       rstorssp -8(%rax, %rsi)
> > >
> > >         /* Save the restore token on the original shadow stack.  */
> > >         saveprevssp
> > > @@ -73,18 +55,12 @@ ENTRY(__push___start_context)
> > >         jmp     __start_context
> > >  1:
> > >
> > > -       /* Get the new shadow stack pointer.  */
> > > -       rdsspq  %rdi
> > > -
> > >         /* Use the restore stoken to restore the original shadow stack.  */
> > > -       rstorssp -8(%r8)
> > > +       rstorssp -8(%rcx)
> > >
> > >         /* Save the restore token on the new shadow stack.  */
> > >         saveprevssp
> > >
> > > -       /* Store the new shadow stack pointer in __ssp[0].  */
> > > -       movq    %rdi, oSSP(%r9)
> > > -
> > >         /* Restore the original stack.  */
> > >         mov     %rdx, %rsp
> > >         ret
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.c b/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.c
> > > new file mode 100644
> > > index 0000000000..f2e1d03b96
> > > --- /dev/null
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.c
> > > @@ -0,0 +1,55 @@
> > > +/* Helper function to allocate shadow stack.
> > > +   Copyright (C) 2023 Free Software Foundation, Inc.
> > > +   This file is part of the GNU C Library.
> > > +
> > > +   The GNU C Library is free software; you can redistribute it and/or
> > > +   modify it under the terms of the GNU Lesser General Public
> > > +   License as published by the Free Software Foundation; either
> > > +   version 2.1 of the License, or (at your option) any later version.
> > > +
> > > +   The GNU C Library is distributed in the hope that it will be useful,
> > > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > > +   Lesser General Public License for more details.
> > > +
> > > +   You should have received a copy of the GNU Lesser General Public
> > > +   License along with the GNU C Library; if not, see
> > > +   <https://www.gnu.org/licenses/>.  */
> > > +
> > > +#include <sysdep.h>
> > > +#include <stdint.h>
> > > +#include <errno.h>
> > > +#include <sys/mman.h>
> > > +#include <libc-pointer-arith.h>
> > > +#include <allocate-shadow-stack.h>
> > > +
> > > +/* NB: This can be treated as a syscall by caller.  */
> > > +
> > > +long int
> > > +__allocate_shadow_stack (size_t stack_size,
> > > +                        shadow_stack_size_t *child_stack)
> > > +{
> > > +#ifdef __NR_map_shadow_stack
> > > +  size_t shadow_stack_size
> > > +    = stack_size >> STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT;
> > > +  /* Align shadow stack to 8 bytes.  */
> > > +  shadow_stack_size = ALIGN_UP (shadow_stack_size, 8);
> > > +  /* Since sigaltstack shares shadow stack with the current context in
> > > +     the thread, add extra 20 stack frames in shadow stack for signal
> > > +     handlers.  */
> > > +  shadow_stack_size += 20 * 8;
> > > +  void *shadow_stack = (void *)INLINE_SYSCALL_CALL
> > > +    (map_shadow_stack, NULL, shadow_stack_size, SHADOW_STACK_SET_TOKEN);
> > > +  /* Report the map_shadow_stack error.  */
> > > +  if (shadow_stack == MAP_FAILED)
> > > +    return -errno;
> > > +
> > > +  /* Save the shadow stack base and size on child stack.  */
> > > +  child_stack[0] = (uintptr_t) shadow_stack;
> > > +  child_stack[1] = shadow_stack_size;
> > > +
> > > +  return 0;
> > > +#else
> > > +  return -ENOSYS;
> > > +#endif
> > > +}
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.h b/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.h
> > > new file mode 100644
> > > index 0000000000..d05aaf16e5
> > > --- /dev/null
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/allocate-shadow-stack.h
> > > @@ -0,0 +1,24 @@
> > > +/* Helper function to allocate shadow stack.
> > > +   Copyright (C) 2023 Free Software Foundation, Inc.
> > > +   This file is part of the GNU C Library.
> > > +
> > > +   The GNU C Library is free software; you can redistribute it and/or
> > > +   modify it under the terms of the GNU Lesser General Public
> > > +   License as published by the Free Software Foundation; either
> > > +   version 2.1 of the License, or (at your option) any later version.
> > > +
> > > +   The GNU C Library is distributed in the hope that it will be useful,
> > > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > > +   Lesser General Public License for more details.
> > > +
> > > +   You should have received a copy of the GNU Lesser General Public
> > > +   License along with the GNU C Library; if not, see
> > > +   <https://www.gnu.org/licenses/>.  */
> > > +
> > > +#include <ucontext.h>
> > > +
> > > +typedef __typeof (((ucontext_t *) 0)->__ssp[0]) shadow_stack_size_t;
> > > +
> > > +extern long int __allocate_shadow_stack (size_t, shadow_stack_size_t *)
> > > +  attribute_hidden;
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/getcontext.S b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
> > > index a00e2f6290..71f3802dca 100644
> > > --- a/sysdeps/unix/sysv/linux/x86_64/getcontext.S
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
> > > @@ -58,35 +58,15 @@ ENTRY(__getcontext)
> > >         testl   $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
> > >         jz      L(no_shstk)
> > >
> > > -       /* Save RDI in RDX which won't be clobbered by syscall.  */
> > > -       movq    %rdi, %rdx
> > > -
> > >         xorl    %eax, %eax
> > >         cmpq    %fs:SSP_BASE_OFFSET, %rax
> > >         jnz     L(shadow_stack_bound_recorded)
> > >
> > > -       /* Get the base address and size of the default shadow stack
> > > -          which must be the current shadow stack since nothing has
> > > -          been recorded yet.  */
> > > -       sub     $24, %RSP_LP
> > > -       mov     %RSP_LP, %RSI_LP
> > > -       movl    $ARCH_CET_STATUS, %edi
> > > -       movl    $__NR_arch_prctl, %eax
> > > -       syscall
> > > -       testq   %rax, %rax
> > > -       jz      L(continue_no_err)
> > > -
> > > -       /* This should never happen.  */
> > > -       hlt
> > > -
> > > -L(continue_no_err):
> > > -       /* Record the base of the current shadow stack.  */
> > > -       movq    8(%rsp), %rax
> > > +       /* When the shadow stack base is unset, the default shadow
> > > +          stack is in use.  Use the current shadow stack pointer
> > > +          as the marker for the default shadow stack.  */
> > > +       rdsspq  %rax
> > >         movq    %rax, %fs:SSP_BASE_OFFSET
> > > -       add     $24, %RSP_LP
> > > -
> > > -       /* Restore RDI.  */
> > > -       movq    %rdx, %rdi
> > >
> > >  L(shadow_stack_bound_recorded):
> > >         /* Get the current shadow stack pointer.  */
> > > @@ -94,7 +74,7 @@ L(shadow_stack_bound_recorded):
> > >         /* NB: Save the caller's shadow stack so that we can jump back
> > >            to the caller directly.  */
> > >         addq    $8, %rax
> > > -       movq    %rax, oSSP(%rdx)
> > > +       movq    %rax, oSSP(%rdi)
> > >
> > >         /* Save the current shadow stack base in ucontext.  */
> > >         movq    %fs:SSP_BASE_OFFSET, %rax
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/makecontext.c b/sysdeps/unix/sysv/linux/x86_64/makecontext.c
> > > index de9e03eb81..e4f025bd50 100644
> > > --- a/sysdeps/unix/sysv/linux/x86_64/makecontext.c
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/makecontext.c
> > > @@ -24,6 +24,7 @@
> > >  # include <pthread.h>
> > >  # include <libc-pointer-arith.h>
> > >  # include <sys/prctl.h>
> > > +# include <allocate-shadow-stack.h>
> > >  #endif
> > >
> > >  #include "ucontext_i.h"
> > > @@ -88,23 +89,24 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
> > >    if ((feature_1 & X86_FEATURE_1_SHSTK) != 0)
> > >      {
> > >        /* Shadow stack is enabled.  We need to allocate a new shadow
> > > -         stack.  */
> > > -      unsigned long ssp_size = (((uintptr_t) sp
> > > -                                - (uintptr_t) ucp->uc_stack.ss_sp)
> > > -                               >> STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT);
> > > -      /* Align shadow stack to 8 bytes.  */
> > > -      ssp_size = ALIGN_UP (ssp_size, 8);
> > > -
> > > -      ucp->__ssp[1] = ssp_size;
> > > -      ucp->__ssp[2] = ssp_size;
> > > -
> > > -      /* Call __push___start_context to allocate a new shadow stack,
> > > -        push __start_context onto the new stack as well as the new
> > > -        shadow stack.  NB: After __push___start_context returns,
> > > +         stack.  NB:
> > >            ucp->__ssp[0]: The new shadow stack pointer.
> > >            ucp->__ssp[1]: The base address of the new shadow stack.
> > >            ucp->__ssp[2]: The size of the new shadow stack.
> > >         */
> > > +      long int ret
> > > +       = __allocate_shadow_stack (((uintptr_t) sp
> > > +                                   - (uintptr_t) ucp->uc_stack.ss_sp),
> > > +                                  &ucp->__ssp[1]);
> > > +      if (ret != 0)
> > > +       {
> > > +         /* FIXME: What should we do?  */
> > > +         abort ();
> > > +       }
> > > +
> > > +      ucp->__ssp[0] = ucp->__ssp[1] + ucp->__ssp[2] - 8;
> > > +      /* Call __push___start_context to push __start_context onto the new
> > > +        stack as well as the new shadow stack.  */
> > >        __push___start_context (ucp);
> > >      }
> > >    else
> > > diff --git a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
> > > index 5925752164..2f2fe9875b 100644
> > > --- a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
> > > +++ b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
> > > @@ -109,25 +109,11 @@ ENTRY(__swapcontext)
> > >         cmpq    %fs:SSP_BASE_OFFSET, %rax
> > >         jnz     L(shadow_stack_bound_recorded)
> > >
> > > -       /* Get the base address and size of the default shadow stack
> > > -          which must be the current shadow stack since nothing has
> > > -          been recorded yet.  */
> > > -       sub     $24, %RSP_LP
> > > -       mov     %RSP_LP, %RSI_LP
> > > -       movl    $ARCH_CET_STATUS, %edi
> > > -       movl    $__NR_arch_prctl, %eax
> > > -       syscall
> > > -       testq   %rax, %rax
> > > -       jz      L(continue_no_err)
> > > -
> > > -       /* This should never happen.  */
> > > -       hlt
> > > -
> > > -L(continue_no_err):
> > > -       /* Record the base of the current shadow stack.  */
> > > -       movq    8(%rsp), %rax
> > > +       /* When the shadow stack base is unset, the default shadow
> > > +          stack is in use.  Use the current shadow stack pointer
> > > +          as the marker for the default shadow stack.  */
> > > +       rdsspq  %rax
> > >         movq    %rax, %fs:SSP_BASE_OFFSET
> > > -       add     $24, %RSP_LP
> > >
> > >  L(shadow_stack_bound_recorded):
> > >          /* If we unwind the stack, we can't undo stack unwinding.  Just
> > > diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> > > index 0bf923d48b..f180f0d9a4 100644
> > > --- a/sysdeps/x86/cpu-features.c
> > > +++ b/sysdeps/x86/cpu-features.c
> > > @@ -1121,8 +1121,9 @@ no_cpuid:
> > >
> > >  # ifndef SHARED
> > >        /* Check if IBT and SHSTK are enabled by kernel.  */
> > > -      if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT)
> > > -         || (cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
> > > +      if ((cet_status
> > > +          & (GNU_PROPERTY_X86_FEATURE_1_IBT
> > > +             | GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
> >
> > I think the code here and elsewhere would be simplifiable with a
> > define/enum of
> > `GNU_PROPERTY_X86_FEATURE_1_SHSTK_OR_IBT =
> > GNU_PROPERTY_X86_FEATURE_1_SHSTK | GNU_PROPERTY_X86_FEATURE_1_IBT`
>
> That may touch more places beyond this patch series.  A separate
> patch after this series has been merged?

Fair enough.
>
> > >         {
> > >           /* Disable IBT and/or SHSTK if they are enabled by kernel, but
> > >              disabled by environment variable:
> > > @@ -1131,9 +1132,11 @@ no_cpuid:
> > >            */
> > >           unsigned int cet_feature = 0;
> > >           if (!CPU_FEATURE_USABLE (IBT))
> > > -           cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> > > +           cet_feature |= (cet_status
> > > +                           & GNU_PROPERTY_X86_FEATURE_1_IBT);
> > >           if (!CPU_FEATURE_USABLE (SHSTK))
> > > -           cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > > +           cet_feature |= (cet_status
> > > +                           & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
> > >
> > >           if (cet_feature)
> > >             {
> > > @@ -1148,7 +1151,9 @@ no_cpuid:
> > >              lock CET if IBT or SHSTK is enabled permissively.  */
> > >           if (GL(dl_x86_feature_control).ibt != cet_permissive
> > >               && GL(dl_x86_feature_control).shstk != cet_permissive)
> > > -           dl_cet_lock_cet ();
> > > +           dl_cet_lock_cet (GL(dl_x86_feature_1)
> > > +                            & (GNU_PROPERTY_X86_FEATURE_1_IBT
> > > +                               | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
> > >         }
> > >  # endif
> > >      }
> > > diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
> > > index e486e549be..66a78244d4 100644
> > > --- a/sysdeps/x86/dl-cet.c
> > > +++ b/sysdeps/x86/dl-cet.c
> > > @@ -202,7 +202,7 @@ dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
> > >         feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > >
> > >        if (feature_1_lock != 0
> > > -         && dl_cet_lock_cet () != 0)
> > > +         && dl_cet_lock_cet (feature_1_lock) != 0)
> > >         _dl_fatal_printf ("%s: can't lock CET\n", info->program);
> > >      }
> > >
> > > diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
> > > index 1403f939f7..4bcc2552a1 100644
> > > --- a/sysdeps/x86_64/nptl/tls.h
> > > +++ b/sysdeps/x86_64/nptl/tls.h
> > > @@ -60,7 +60,7 @@ typedef struct
> > >    void *__private_tm[4];
> > >    /* GCC split stack support.  */
> > >    void *__private_ss;
> > > -  /* The lowest address of shadow stack,  */
> > > +  /* The marker for the current shadow stack.  */
> > >    unsigned long long int ssp_base;
> > >    /* Must be kept even if it is no longer used by glibc since programs,
> > >       like AddressSanitizer, depend on the size of tcbhead_t.  */
> > > --
> > > 2.43.0
> > >
>
>
>
> --
> H.J.

  reply	other threads:[~2023-12-27  0:40 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-22 16:58 [PATCH v5 0/6] x86/cet: Update CET kernel interface H.J. Lu
2023-12-22 16:58 ` [PATCH v5 1/6] x86/cet: Sync with Linux kernel 6.6 shadow stack interface H.J. Lu
2023-12-26 17:37   ` Noah Goldstein
2023-12-26 17:56     ` H.J. Lu
2023-12-27  0:40       ` Noah Goldstein [this message]
2023-12-22 16:58 ` [PATCH v5 2/6] elf: Always provide _dl_get_dl_main_map in libc.a H.J. Lu
2023-12-29 14:45   ` Adhemerval Zanella Netto
2023-12-29 15:15     ` H.J. Lu
2023-12-22 16:58 ` [PATCH v5 3/6] x86/cet: Enable shadow stack during startup H.J. Lu
2023-12-29 14:55   ` Adhemerval Zanella Netto
2023-12-29 15:24     ` H.J. Lu
2023-12-22 16:58 ` [PATCH v5 4/6] x86/cet: Check feature_1 in TCB for active IBT and SHSTK H.J. Lu
2023-12-29 14:59   ` Adhemerval Zanella Netto
2023-12-29 15:14     ` H.J. Lu
2023-12-22 16:58 ` [PATCH v5 5/6] x86/cet: Don't set CET active by default H.J. Lu
2023-12-22 16:58 ` [PATCH v5 6/6] x86/cet: Run some CET tests with shadow stack H.J. Lu
2023-12-28 16:00 ` [PATCH v5 0/6] x86/cet: Update CET kernel interface Florian Weimer
2023-12-28 21:17   ` H.J. Lu

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=CAFUsyfJyzuUD8Z1LV3_5BvtcmjvQSs+7ctLeFzkbJhyJ_60BgQ@mail.gmail.com \
    --to=goldstein.w.n@gmail.com \
    --cc=hjl.tools@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).