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.
next prev parent 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).