diff mbox series

[v2] x32/cet: Enable shadow stack during startup for Linux 6.10

Message ID 20240721230420.3684982-1-hjl.tools@gmail.com
State New
Headers show
Series [v2] x32/cet: Enable shadow stack during startup for Linux 6.10 | expand

Commit Message

H.J. Lu July 21, 2024, 11:04 p.m. UTC
Enable shadow stack during startup for Linux 6.10:

commit 2883f01ec37dd8668e7222dfdb5980c86fdfe277
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Mar 15 07:04:33 2024 -0700

    x86/shstk: Enable shadow stacks for x32

    1. Add shadow stack support to x32 signal.
    2. Use the 64-bit map_shadow_stack syscall for x32.
    3. Set up shadow stack for x32.

Add the map_shadow_stack system call to <fixup-asm-unistd.h> and regenerate
arch-syscall.h.  Tested on Intel Tiger Lake.
---
 sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h     | 1 +
 sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h | 4 ++++
 sysdeps/x86_64/x32/dl-machine.h                       | 7 +++++--
 3 files changed, 10 insertions(+), 2 deletions(-)

Comments

Noah Goldstein July 22, 2024, 11:36 a.m. UTC | #1
On Mon, Jul 22, 2024 at 7:04 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Enable shadow stack during startup for Linux 6.10:
>
> commit 2883f01ec37dd8668e7222dfdb5980c86fdfe277
> Author: H.J. Lu <hjl.tools@gmail.com>
> Date:   Fri Mar 15 07:04:33 2024 -0700
>
>     x86/shstk: Enable shadow stacks for x32
>
>     1. Add shadow stack support to x32 signal.
>     2. Use the 64-bit map_shadow_stack syscall for x32.
>     3. Set up shadow stack for x32.
>
> Add the map_shadow_stack system call to <fixup-asm-unistd.h> and regenerate
> arch-syscall.h.  Tested on Intel Tiger Lake.
> ---
>  sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h     | 1 +
>  sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h | 4 ++++
>  sysdeps/x86_64/x32/dl-machine.h                       | 7 +++++--
>  3 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> index 3040a47d72..df3e22236d 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> @@ -155,6 +155,7 @@
>  #define __NR_lsm_set_self_attr 1073742284
>  #define __NR_lstat 1073741830
>  #define __NR_madvise 1073741852
> +#define __NR_map_shadow_stack 1073742277
>  #define __NR_mbind 1073742061
>  #define __NR_membarrier 1073742148
>  #define __NR_memfd_create 1073742143
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> index 98124169e6..47fa8af4ce 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> @@ -15,6 +15,10 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>
> +#ifndef __NR_map_shadow_stack
> +# define __NR_map_shadow_stack 1073742277
> +#endif
> +
>  /* X32 uses the same 64-bit syscall interface for set_thread_area.   */
>  #ifndef __NR_set_thread_area
>  # define __NR_set_thread_area 1073742029
> diff --git a/sysdeps/x86_64/x32/dl-machine.h b/sysdeps/x86_64/x32/dl-machine.h
> index c35cee9261..3eb59bde7c 100644
> --- a/sysdeps/x86_64/x32/dl-machine.h
> +++ b/sysdeps/x86_64/x32/dl-machine.h
> @@ -45,13 +45,16 @@ _start:\n\
>  _dl_start_user:\n\
>         # Save the user entry point address in %r12.\n\
>         movl %eax, %r12d\n\
> +       # Save %rsp value in %r13.\n\
> +       movl %esp, %r13d\n\
> +"\
> +       RTLD_START_ENABLE_X86_FEATURES \
> +"\
>         # Read the original argument count.\n\
>         movl (%rsp), %edx\n\
>         # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
>         # argc -> rsi\n\
>         movl %edx, %esi\n\
> -       # Save %rsp value in %r13.\n\
> -       movl %esp, %r13d\n\
>         # And align stack for the _dl_init call.\n\
>         and $-16, %esp\n\
>         # _dl_loaded -> rdi\n\
> --
> 2.45.2
>

Could the RTLD_START could be shared between x32/x64 using the:
`sysdeps/x86_64/multiarch/reg-macros.h"?

Thinking something like:
```
#define RTLD_RSP "%" STRINGIFY(VRSP)
#define RTLD_RAX "%" STRINGIFY(VRAX)
#define RTLD_RCX "%" STRINGIFY(VRCX)
#define RTLD_RDX "%" STRINGIFY(VRDX)
#define RTLD_RSI "%" STRINGIFY(VRSI)
#define RTLD_RDI "%" STRINGIFY(VRDI)
#define RTLD_R13 "%" STRINGIFY(VR13)
#define RTLD_R12 "%" STRINGIFY(VR12)

#define RTLD_START asm ("\n\
.text\n\
.p2align " STRINGIFY(RTLD_ALIGN) "\n        \
.globl _start\n\
.globl _dl_start_user\n\
_start:\n\
movl " RTLD_RSP "," RTLD_RDI "\n\
call _dl_start\n\
_dl_start_user:\n\
# Save the user entry point address in %r12.\n\
movl " RTLD_RAX ", " RTLD_R12 "\n\
# Save %rsp value in %r13.\n\
movl " RTLD_RSP ", " RTLD_R13 "\n\
"\
RTLD_START_ENABLE_X86_FEATURES \
"\
# Read the original argument count.\n\
movl (%rsp), " RTLD_RDX "\n\
# Call _dl_init (struct link_map *main_map, int argc, char **argv,
char **env)\n\
# argc -> rsi\n\
movl " RTLD_RDX ", " RTLD_RSI "\n\
# And align stack for the _dl_init call.\n\
and $-16, " RTLD_RSP "\n\
# _dl_loaded -> rdi\n\
movl _rtld_local(%rip), " RTLD_RDI "\n\
# env -> rcx\n\
lea 8(%r13,%rdx,4), " RTLD_RCX "\n\
# argv -> rdx\n\
lea 4(%r13), " RTLD_RDX "\n\
# Clear %rbp to mark outermost frame obviously even for constructors.\n\
xorl %ebp, %ebp\n\
# Call the function to run the initializers.\n\
call _dl_init\n\
# Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
lea _dl_fini(%rip), " RTLD_RDX "\n\
# And make sure %rsp points to argc stored on the stack.\n\
movl " RTLD_R13 ", " RTLD_RSP "\n\
# Jump to the user's entry point.\n\
jmp *%r12\n\
.previous\n\
");

```

Width `REG_WIDTH` defined as 4 for x32 and 8 for x64. (And align
as 4 and 16 respectively).
H.J. Lu July 23, 2024, 12:56 a.m. UTC | #2
On Mon, Jul 22, 2024, 7:37 PM Noah Goldstein <goldstein.w.n@gmail.com>
wrote:

> On Mon, Jul 22, 2024 at 7:04 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > Enable shadow stack during startup for Linux 6.10:
> >
> > commit 2883f01ec37dd8668e7222dfdb5980c86fdfe277
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Fri Mar 15 07:04:33 2024 -0700
> >
> >     x86/shstk: Enable shadow stacks for x32
> >
> >     1. Add shadow stack support to x32 signal.
> >     2. Use the 64-bit map_shadow_stack syscall for x32.
> >     3. Set up shadow stack for x32.
> >
> > Add the map_shadow_stack system call to <fixup-asm-unistd.h> and
> regenerate
> > arch-syscall.h.  Tested on Intel Tiger Lake.
> > ---
> >  sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h     | 1 +
> >  sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h | 4 ++++
> >  sysdeps/x86_64/x32/dl-machine.h                       | 7 +++++--
> >  3 files changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> > index 3040a47d72..df3e22236d 100644
> > --- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
> > @@ -155,6 +155,7 @@
> >  #define __NR_lsm_set_self_attr 1073742284
> >  #define __NR_lstat 1073741830
> >  #define __NR_madvise 1073741852
> > +#define __NR_map_shadow_stack 1073742277
> >  #define __NR_mbind 1073742061
> >  #define __NR_membarrier 1073742148
> >  #define __NR_memfd_create 1073742143
> > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> > index 98124169e6..47fa8af4ce 100644
> > --- a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
> > @@ -15,6 +15,10 @@
> >     License along with the GNU C Library; if not, see
> >     <http://www.gnu.org/licenses/>.  */
> >
> > +#ifndef __NR_map_shadow_stack
> > +# define __NR_map_shadow_stack 1073742277
> > +#endif
> > +
> >  /* X32 uses the same 64-bit syscall interface for set_thread_area.   */
> >  #ifndef __NR_set_thread_area
> >  # define __NR_set_thread_area 1073742029
> > diff --git a/sysdeps/x86_64/x32/dl-machine.h
> b/sysdeps/x86_64/x32/dl-machine.h
> > index c35cee9261..3eb59bde7c 100644
> > --- a/sysdeps/x86_64/x32/dl-machine.h
> > +++ b/sysdeps/x86_64/x32/dl-machine.h
> > @@ -45,13 +45,16 @@ _start:\n\
> >  _dl_start_user:\n\
> >         # Save the user entry point address in %r12.\n\
> >         movl %eax, %r12d\n\
> > +       # Save %rsp value in %r13.\n\
> > +       movl %esp, %r13d\n\
> > +"\
> > +       RTLD_START_ENABLE_X86_FEATURES \
> > +"\
> >         # Read the original argument count.\n\
> >         movl (%rsp), %edx\n\
> >         # Call _dl_init (struct link_map *main_map, int argc, char
> **argv, char **env)\n\
> >         # argc -> rsi\n\
> >         movl %edx, %esi\n\
> > -       # Save %rsp value in %r13.\n\
> > -       movl %esp, %r13d\n\
> >         # And align stack for the _dl_init call.\n\
> >         and $-16, %esp\n\
> >         # _dl_loaded -> rdi\n\
> > --
> > 2.45.2
> >
>
> Could the RTLD_START could be shared between x32/x64 using the:
> `sysdeps/x86_64/multiarch/reg-macros.h"?
>

I sent the v3 patch set to remove x32
dl-machine.h.


> Thinking something like:
> ```
> #define RTLD_RSP "%" STRINGIFY(VRSP)
> #define RTLD_RAX "%" STRINGIFY(VRAX)
> #define RTLD_RCX "%" STRINGIFY(VRCX)
> #define RTLD_RDX "%" STRINGIFY(VRDX)
> #define RTLD_RSI "%" STRINGIFY(VRSI)
> #define RTLD_RDI "%" STRINGIFY(VRDI)
> #define RTLD_R13 "%" STRINGIFY(VR13)
> #define RTLD_R12 "%" STRINGIFY(VR12)
>
> #define RTLD_START asm ("\n\
> .text\n\
> .p2align " STRINGIFY(RTLD_ALIGN) "\n        \
> .globl _start\n\
> .globl _dl_start_user\n\
> _start:\n\
> movl " RTLD_RSP "," RTLD_RDI "\n\
> call _dl_start\n\
> _dl_start_user:\n\
> # Save the user entry point address in %r12.\n\
> movl " RTLD_RAX ", " RTLD_R12 "\n\
> # Save %rsp value in %r13.\n\
> movl " RTLD_RSP ", " RTLD_R13 "\n\
> "\
> RTLD_START_ENABLE_X86_FEATURES \
> "\
> # Read the original argument count.\n\
> movl (%rsp), " RTLD_RDX "\n\
> # Call _dl_init (struct link_map *main_map, int argc, char **argv,
> char **env)\n\
> # argc -> rsi\n\
> movl " RTLD_RDX ", " RTLD_RSI "\n\
> # And align stack for the _dl_init call.\n\
> and $-16, " RTLD_RSP "\n\
> # _dl_loaded -> rdi\n\
> movl _rtld_local(%rip), " RTLD_RDI "\n\
> # env -> rcx\n\
> lea 8(%r13,%rdx,4), " RTLD_RCX "\n\
> # argv -> rdx\n\
> lea 4(%r13), " RTLD_RDX "\n\
> # Clear %rbp to mark outermost frame obviously even for constructors.\n\
> xorl %ebp, %ebp\n\
> # Call the function to run the initializers.\n\
> call _dl_init\n\
> # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
> lea _dl_fini(%rip), " RTLD_RDX "\n\
> # And make sure %rsp points to argc stored on the stack.\n\
> movl " RTLD_R13 ", " RTLD_RSP "\n\
> # Jump to the user's entry point.\n\
> jmp *%r12\n\
> .previous\n\
> ");
>
> ```
>
> Width `REG_WIDTH` defined as 4 for x32 and 8 for x64. (And align
> as 4 and 16 respectively).
>
>
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
index 3040a47d72..df3e22236d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
@@ -155,6 +155,7 @@ 
 #define __NR_lsm_set_self_attr 1073742284
 #define __NR_lstat 1073741830
 #define __NR_madvise 1073741852
+#define __NR_map_shadow_stack 1073742277
 #define __NR_mbind 1073742061
 #define __NR_membarrier 1073742148
 #define __NR_memfd_create 1073742143
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
index 98124169e6..47fa8af4ce 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
@@ -15,6 +15,10 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef __NR_map_shadow_stack
+# define __NR_map_shadow_stack 1073742277
+#endif
+
 /* X32 uses the same 64-bit syscall interface for set_thread_area.   */
 #ifndef __NR_set_thread_area
 # define __NR_set_thread_area 1073742029
diff --git a/sysdeps/x86_64/x32/dl-machine.h b/sysdeps/x86_64/x32/dl-machine.h
index c35cee9261..3eb59bde7c 100644
--- a/sysdeps/x86_64/x32/dl-machine.h
+++ b/sysdeps/x86_64/x32/dl-machine.h
@@ -45,13 +45,16 @@  _start:\n\
 _dl_start_user:\n\
 	# Save the user entry point address in %r12.\n\
 	movl %eax, %r12d\n\
+	# Save %rsp value in %r13.\n\
+	movl %esp, %r13d\n\
+"\
+	RTLD_START_ENABLE_X86_FEATURES \
+"\
 	# Read the original argument count.\n\
 	movl (%rsp), %edx\n\
 	# Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
 	# argc -> rsi\n\
 	movl %edx, %esi\n\
-	# Save %rsp value in %r13.\n\
-	movl %esp, %r13d\n\
 	# And align stack for the _dl_init call.\n\
 	and $-16, %esp\n\
 	# _dl_loaded -> rdi\n\