[PATCH v2 04/14] riscv: Adjust assembly routines to support landing pad

Heinrich Schuchardt heinrich.schuchardt@canonical.com
Wed Jul 23 08:31:08 GMT 2025


On 23.07.25 09:23, Jesse Huang wrote:
> Do you have any concern that we are going to change something as about 
> unlabel scheme in the future?

Labelled landing pads offer better security guarantees than unlabeled 
ones. Therefore, it can be expected that the segment of the ecosystem 
focused on control flow integrity will converge on using labelled 
landing pads.

For Linux distributions it is of interest to have a migration path from 
unlabelled to labelled landing pads where at some moments in time not 
all packages are recompiled. So for a distro it would be preferable to 
be able to move via these stages:

1) packages compiled for unlabelled landing pads
2) packages compiled with unlabelled landing pads but x7 already set up 
with label
3) packages compiled for labelled landing pads

Here a mix of 1) and 2) packages or a mix of 2) and 3) packages should 
not pose any compatibility problems as unlabelled landing pads simply 
ignore the x7 register.

Best regards

Heinrich

> 
> 2025年7月23日(水) 4:28 Deepak Gupta <debug@rivosinc.com 
> <mailto:debug@rivosinc.com>>:
> 
>     On Fri, Jul 11, 2025 at 06:52:45AM -0700, Jesse Huang wrote:
>      >Landing pads, instructions for setting the label value as well as
>      >alignment directives are inserted at where they should be.
>      >
>      >Frame offsets for floating point registers in _dl_runtime_resolve
>      >are also adjusted because now t2 has to be saved onto the stack.
>      >
>      >Co-authored-by: Hau Hsu <hau.hsu@sifive.com
>     <mailto:hau.hsu@sifive.com>>
>      >Co-authored-by: Kito Cheng <kito.cheng@sifive.com
>     <mailto:kito.cheng@sifive.com>>
>      >---
>      > sysdeps/riscv/__longjmp.S                    |  1 +
>      > sysdeps/riscv/crti.S                         |  4 ++
>      > sysdeps/riscv/crtn.S                         |  4 ++
>      > sysdeps/riscv/dl-machine.h                   |  8 +++
>      > sysdeps/riscv/dl-trampoline.S                | 61 +++++++++++------
>      > sysdeps/riscv/multiarch/memcpy_noalignment.S |  4 ++
>      > sysdeps/riscv/setjmp.S                       |  3 +
>      > sysdeps/riscv/start.S                        | 10 +++
>      > sysdeps/unix/sysv/linux/riscv/clone.S        |  2 +
>      > sysdeps/unix/sysv/linux/riscv/sysdep.S       |  1 +
>      > sysdeps/unix/sysv/linux/riscv/sysdep.h       | 71 +++++++++++++++
>     +++++
>      > sysdeps/unix/sysv/linux/riscv/vfork.S        |  1 +
>      > 12 files changed, 150 insertions(+), 20 deletions(-)
>      > create mode 100644 sysdeps/riscv/crti.S
>      > create mode 100644 sysdeps/riscv/crtn.S
>      >
>      >diff --git a/sysdeps/riscv/__longjmp.S b/sysdeps/riscv/__longjmp.S
>      >index 7228b457a6..47ff3aa09e 100644
>      >--- a/sysdeps/riscv/__longjmp.S
>      >+++ b/sysdeps/riscv/__longjmp.S
>      >@@ -20,6 +20,7 @@
>      > #include <sys/asm.h>
>      >
>      > ENTRY (__longjmp)
>      >+      LPAD
>      >       REG_L ra,  0*SZREG(a0)
>      >       REG_L s0,  1*SZREG(a0)
>      >       REG_L s1,  2*SZREG(a0)
>      >diff --git a/sysdeps/riscv/crti.S b/sysdeps/riscv/crti.S
>      >new file mode 100644
>      >index 0000000000..fb1097c5ca
>      >--- /dev/null
>      >+++ b/sysdeps/riscv/crti.S
>      >@@ -0,0 +1,4 @@
>      >+/* crti.S is empty because .init_array/.fini_array are used
>     exclusively.
>      >+   Include sysdep.h to define gnu property if necessary. */
>      >+
>      >+#include <sysdep.h>
>      >diff --git a/sysdeps/riscv/crtn.S b/sysdeps/riscv/crtn.S
>      >new file mode 100644
>      >index 0000000000..b2e7cb692e
>      >--- /dev/null
>      >+++ b/sysdeps/riscv/crtn.S
>      >@@ -0,0 +1,4 @@
>      >+/* crtn.S is empty because .init_array/.fini_array are used
>     exclusively.
>      >+   Include sysdep.h to define gnu property if necessary. */
>      >+
>      >+#include <sysdep.h>
>      >diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
>      >index dcc3e0883b..76f43a242b 100644
>      >--- a/sysdeps/riscv/dl-machine.h
>      >+++ b/sysdeps/riscv/dl-machine.h
>      >@@ -28,6 +28,13 @@
>      > #include <dl-irel.h>
>      > #include <dl-static-tls.h>
>      > #include <dl-machine-rel.h>
>      >+/* This is a marker to remind us to add real expansion to setup
>     the label
>      >+   for the function signature label scheme in the future  */
>      >+#ifdef __riscv_landing_pad_unlabeled
>      >+# define SET_LPAD
>      >+#else
>      >+# define SET_LPAD
>      >+#endif
>      >
>      > #ifndef _RTLD_PROLOGUE
>      > # define _RTLD_PROLOGUE(entry)                                   
>                  \
>      >@@ -126,6 +133,7 @@ elf_machine_dynamic (void)
>      >       # Pass our finalizer function to _start.\n\
>      >       lla a0, _dl_fini\n\
>      >       # Jump to the user entry point.\n\
>      >+        " STRINGXV (SET_LPAD) "\n\
>      >       jr s0\n\
>      >       " _RTLD_EPILOGUE (ENTRY_POINT) \
>      >         _RTLD_EPILOGUE (_dl_start_user) "\
>      >diff --git a/sysdeps/riscv/dl-trampoline.S b/sysdeps/riscv/dl-
>     trampoline.S
>      >index 93d04af326..2b25f64a3b 100644
>      >--- a/sysdeps/riscv/dl-trampoline.S
>      >+++ b/sysdeps/riscv/dl-trampoline.S
>      >@@ -25,13 +25,27 @@
>      > /* Assembler veneer called from the PLT header code for lazy loading.
>      >    The PLT header passes its own args in t0-t2.  */
>      >
>      >-#ifdef __riscv_float_abi_soft
>      >-# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
>      >-#else
>      >-# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
>      >+#ifdef __riscv_landing_pad
>      >+
>      >+# ifdef __riscv_float_abi_soft
>      >+#  define FRAME_SIZE (-((-11 * SZREG) & ALMASK))
>      >+# else
>      >+#  define FRAME_SIZE (-((-11 * SZREG - 8 * SZFREG) & ALMASK))
>      >+#  define FREG_BASE_OFFSET (11*SZREG)
>      >+# endif
>      >+
>      >+# else
>      >+
>      >+# ifdef __riscv_float_abi_soft
>      >+#  define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
>      >+# else
>      >+#  define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
>      >+#  define FREG_BASE_OFFSET (10*SZREG)
>      >+# endif
>      > #endif
>      >
>      > ENTRY (_dl_runtime_resolve)
>      >+  LPAD
>      >   # Save arguments to stack.
>      >   addi sp, sp, -FRAME_SIZE
>      >   REG_S ra, 9*SZREG(sp)
>      >@@ -43,16 +57,19 @@ ENTRY (_dl_runtime_resolve)
>      >   REG_S a5, 6*SZREG(sp)
>      >   REG_S a6, 7*SZREG(sp)
>      >   REG_S a7, 8*SZREG(sp)
>      >+#ifdef __riscv_landing_pad
>      >+  REG_S t2, 10*SZREG(sp)
>      >+#endif
>      >
>      > #ifndef __riscv_float_abi_soft
>      >-  FREG_S fa0, (10*SZREG + 0*SZFREG)(sp)
>      >-  FREG_S fa1, (10*SZREG + 1*SZFREG)(sp)
>      >-  FREG_S fa2, (10*SZREG + 2*SZFREG)(sp)
>      >-  FREG_S fa3, (10*SZREG + 3*SZFREG)(sp)
>      >-  FREG_S fa4, (10*SZREG + 4*SZFREG)(sp)
>      >-  FREG_S fa5, (10*SZREG + 5*SZFREG)(sp)
>      >-  FREG_S fa6, (10*SZREG + 6*SZFREG)(sp)
>      >-  FREG_S fa7, (10*SZREG + 7*SZFREG)(sp)
>      >+  FREG_S fa0, (FREG_BASE_OFFSET + 0*SZFREG)(sp)
>      >+  FREG_S fa1, (FREG_BASE_OFFSET + 1*SZFREG)(sp)
>      >+  FREG_S fa2, (FREG_BASE_OFFSET + 2*SZFREG)(sp)
>      >+  FREG_S fa3, (FREG_BASE_OFFSET + 3*SZFREG)(sp)
>      >+  FREG_S fa4, (FREG_BASE_OFFSET + 4*SZFREG)(sp)
>      >+  FREG_S fa5, (FREG_BASE_OFFSET + 5*SZFREG)(sp)
>      >+  FREG_S fa6, (FREG_BASE_OFFSET + 6*SZFREG)(sp)
>      >+  FREG_S fa7, (FREG_BASE_OFFSET + 7*SZFREG)(sp)
>      > #endif
>      >
>      >   # Update .got.plt and obtain runtime address of callee.
>      >@@ -60,6 +77,7 @@ ENTRY (_dl_runtime_resolve)
>      >   mv a0, t0       # link map
>      >   add a1, a1, t1  # reloc offset (== thrice the .got.plt offset)
>      >   la a2, _dl_fixup
>      >+  SET_LPAD
>      >   jalr a2
>      >   mv t1, a0
>      >
>      >@@ -73,16 +91,19 @@ ENTRY (_dl_runtime_resolve)
>      >   REG_L a5, 6*SZREG(sp)
>      >   REG_L a6, 7*SZREG(sp)
>      >   REG_L a7, 8*SZREG(sp)
>      >+#ifdef __riscv_landing_pad
>      >+  REG_L t2, 10*SZREG(sp)
>      >+#endif
>      >
>      > #ifndef __riscv_float_abi_soft
>      >-  FREG_L fa0, (10*SZREG + 0*SZFREG)(sp)
>      >-  FREG_L fa1, (10*SZREG + 1*SZFREG)(sp)
>      >-  FREG_L fa2, (10*SZREG + 2*SZFREG)(sp)
>      >-  FREG_L fa3, (10*SZREG + 3*SZFREG)(sp)
>      >-  FREG_L fa4, (10*SZREG + 4*SZFREG)(sp)
>      >-  FREG_L fa5, (10*SZREG + 5*SZFREG)(sp)
>      >-  FREG_L fa6, (10*SZREG + 6*SZFREG)(sp)
>      >-  FREG_L fa7, (10*SZREG + 7*SZFREG)(sp)
>      >+  FREG_L fa0, (FREG_BASE_OFFSET + 0*SZFREG)(sp)
>      >+  FREG_L fa1, (FREG_BASE_OFFSET + 1*SZFREG)(sp)
>      >+  FREG_L fa2, (FREG_BASE_OFFSET + 2*SZFREG)(sp)
>      >+  FREG_L fa3, (FREG_BASE_OFFSET + 3*SZFREG)(sp)
>      >+  FREG_L fa4, (FREG_BASE_OFFSET + 4*SZFREG)(sp)
>      >+  FREG_L fa5, (FREG_BASE_OFFSET + 5*SZFREG)(sp)
>      >+  FREG_L fa6, (FREG_BASE_OFFSET + 6*SZFREG)(sp)
>      >+  FREG_L fa7, (FREG_BASE_OFFSET + 7*SZFREG)(sp)
>      > #endif
>      >
>      >   addi sp, sp, FRAME_SIZE
>      >diff --git a/sysdeps/riscv/multiarch/memcpy_noalignment.S b/
>     sysdeps/riscv/multiarch/memcpy_noalignment.S
>      >index dd135f4a4d..e97748e82b 100644
>      >--- a/sysdeps/riscv/multiarch/memcpy_noalignment.S
>      >+++ b/sysdeps/riscv/multiarch/memcpy_noalignment.S
>      >@@ -34,7 +34,11 @@
>      > #define BLOCK_SIZE (16 * SZREG)
>      >
>      >       .attribute unaligned_access, 1
>      >+#ifdef __riscv_landing_pad
>      >+        .align  2
>      >+#endif
>      > ENTRY (__memcpy_noalignment)
>      >+        LPAD
>      >       beq     a2, zero, L(ret)
>      >
>      >       /* if LEN < SZREG jump to tail handling.  */
>      >diff --git a/sysdeps/riscv/setjmp.S b/sysdeps/riscv/setjmp.S
>      >index 600ea84db6..df048cb544 100644
>      >--- a/sysdeps/riscv/setjmp.S
>      >+++ b/sysdeps/riscv/setjmp.S
>      >@@ -20,14 +20,17 @@
>      > #include <sys/asm.h>
>      >
>      > ENTRY (_setjmp)
>      >+  LPAD
>      >   li  a1, 0
>      >   j   HIDDEN_JUMPTARGET (__sigsetjmp)
>      > END (_setjmp)
>      > ENTRY (setjmp)
>      >+  LPAD
>      >   li  a1, 1
>      >   /* Fallthrough */
>      > END (setjmp)
>      > ENTRY (__sigsetjmp)
>      >+      LPAD
>      >       REG_S ra,  0*SZREG(a0)
>      >       REG_S s0,  1*SZREG(a0)
>      >       REG_S s1,  2*SZREG(a0)
>      >diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S
>      >index 2db79c0ae6..ff083b13a4 100644
>      >--- a/sysdeps/riscv/start.S
>      >+++ b/sysdeps/riscv/start.S
>      >@@ -47,12 +47,14 @@ ENTRY (ENTRY_POINT)
>      >          .cfi_label to force starting the FDE.  */
>      >       .cfi_label .Ldummy
>      >       cfi_undefined (ra)
>      >+      LPAD
>      >       call  load_gp
>      >       mv    a5, a0  /* rtld_fini.  */
>      >       /* main may be in a shared library.  */
>      > #if defined PIC && !defined SHARED
>      >       /* Avoid relocation in static PIE since _start is called
>     before it
>      >          is relocated.  */
>      >+      SET_LPAD
>      >       lla   a0, __wrap_main
>      > #else
>      >       la   a0, main
>      >@@ -69,7 +71,11 @@ ENTRY (ENTRY_POINT)
>      > END (ENTRY_POINT)
>      >
>      > #if defined PIC && !defined SHARED
>      >+#ifdef __riscv_landing_pad
>      >+      .align 2
>      >+#endif /* __riscv_landing_pad  */
>      > __wrap_main:
>      >+      LPAD
>      >       tail  main@plt
>      > #endif
>      >
>      >@@ -79,9 +85,13 @@ __wrap_main:
>      >    needs to be initialized before calling __libc_start_main in
>     that case.
>      >    So we redundantly initialize it at the beginning of _start.  */
>      >
>      >+#ifdef __riscv_landing_pad
>      >+      .align 2
>      >+#endif /* __riscv_landing_pad  */
>      > load_gp:
>      > .option push
>      > .option norelax
>      >+      LPAD
>      >       lla   gp, __global_pointer$
>      > .option pop
>      >       ret
>      >diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/
>     sysv/linux/riscv/clone.S
>      >index 1362dd9c22..d6a0996ec8 100644
>      >--- a/sysdeps/unix/sysv/linux/riscv/clone.S
>      >+++ b/sysdeps/unix/sysv/linux/riscv/clone.S
>      >@@ -31,6 +31,7 @@
>      >
>      >       .text
>      > LEAF (__clone)
>      >+      LPAD
>      >
>      >       /* Align stack to a 128-bit boundary as per RISC-V ABI.  */
>      >       andi            a1,a1,ALMASK
>      >@@ -82,6 +83,7 @@ L (thread_start):
>      >       REG_L           a0,SZREG(sp)    /* Argument pointer.  */
>      >
>      >       /* Call the user's function.  */
>      >+      SET_LPAD
>      >       jalr            a1
>      >
>      >       /* Call exit with the function's return value.  */
>      >diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.S b/sysdeps/
>     unix/sysv/linux/riscv/sysdep.S
>      >index b50671b9b7..e7ea424e45 100644
>      >--- a/sysdeps/unix/sysv/linux/riscv/sysdep.S
>      >+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.S
>      >@@ -23,6 +23,7 @@
>      > #endif
>      >
>      > ENTRY (__syscall_error)
>      >+      LPAD
>      >       mv t0, ra
>      >       /* Fall through to __syscall_set_errno.  */
>      > END (__syscall_error)
>      >diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/
>     unix/sysv/linux/riscv/sysdep.h
>      >index ee015dfeb6..14a1f3a647 100644
>      >--- a/sysdeps/unix/sysv/linux/riscv/sysdep.h
>      >+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
>      >@@ -53,6 +53,75 @@
>      >
>      > # include <sys/asm.h>
>      >
>      >+/* GNU_PROPERTY_RISCV_* macros from elf.h for use in asm code.  */
>      >+#define FEATURE_1_AND 0xc0000000
>      >+
>      >+/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
>      >+#if __riscv_xlen == 32
>      >+# define GNU_PROPERTY(type, value)    \
>      >+   .section .note.gnu.property, "a";  \
>      >+   .p2align 2;                                \
>      >+   .word 4;                           \
>      >+   .word 12;                          \
>      >+   .word 5;                           \
>      >+   .asciz "GNU";                      \
>      >+   .word type;                                \
>      >+   .word 4;                           \
>      >+   .word value;                               \
>      >+   .text
>      >+#else
>      >+# define GNU_PROPERTY(type, value)    \
>      >+   .section .note.gnu.property, "a";  \
>      >+   .p2align 3;                                \
>      >+   .word 4;                           \
>      >+   .word 16;                          \
>      >+   .word 5;                           \
>      >+   .asciz "GNU";                      \
>      >+   .word type;                                \
>      >+   .word 4;                           \
>      >+   .word value;                               \
>      >+   .word 0;                           \
>      >+   .text
>      >+#endif
> 
>     + Heinrich
> 
>     Do we need a version field for unlabeled landing pad scheme?
>     I have raised it with Kito, for labeled one's we need version for sure.
>     Although if we start with unlabaled gnu property, it will look
>     canonical.
> 
>      >+
>      >+/* Add GNU property note with the supported features to all asm code
>      >+   where sysdep.h is included.  */
>      >+#undef __VALUE_FOR_FEATURE_1_AND
>      >+#if defined (__riscv_landing_pad) || defined (__riscv_shadow_stack)
>      >+#  if defined (__riscv_landing_pad_unlabeled)
>      >+#    if defined (__riscv_shadow_stack)
>      >+#      define __VALUE_FOR_FEATURE_1_AND 0x3
>      >+#    else
>      >+#      define __VALUE_FOR_FEATURE_1_AND 0x1
>      >+#    endif
>      >+#  elif defined (__riscv_landing_pad_func_sig)
>      >+#    if defined (__riscv_shadow_stack)
>      >+#      define __VALUE_FOR_FEATURE_1_AND 0x6
>      >+#    else
>      >+#      define __VALUE_FOR_FEATURE_1_AND 0x4
>      >+#    endif
>      >+#  else
>      >+#    if defined (__riscv_shadow_stack)
>      >+#      define __VALUE_FOR_FEATURE_1_AND 0x2
>      >+#    else
>      >+#      error "What?"
>      >+#    endif
>      >+#  endif
>      >+#endif
>      >+
>      >+#if defined (__VALUE_FOR_FEATURE_1_AND)
>      >+GNU_PROPERTY (FEATURE_1_AND, __VALUE_FOR_FEATURE_1_AND)
>      >+#endif
>      >+#undef __VALUE_FOR_FEATURE_1_AND
>      >+
>      >+#ifdef __riscv_landing_pad_unlabeled
>      >+# define SET_LPAD
>      >+# define LPAD       lpad 0
>      >+#else
>      >+# define SET_LPAD
>      >+# define LPAD
>      >+#endif
>      >+
>      > # define ENTRY(name) LEAF(name)
>      >
>      > # define L(label) .L ## label
>      >@@ -64,6 +133,7 @@
>      >   .text;                                                      \
>      >   .align 2;                                                   \
>      >   ENTRY (name);                                                 
>           \
>      >+  LPAD;                                                       \
>      >   li a7, SYS_ify (syscall_name);                              \
>      >   scall;                                                      \
>      >   li a7, -4096;                                                 
>           \
>      >@@ -111,6 +181,7 @@
>      > # define PSEUDO_NOERRNO(name, syscall_name, args)     \
>      >   .align 2;                                           \
>      >   ENTRY (name);                                               \
>      >+  LPAD;                                               \
>      >   li a7, SYS_ify (syscall_name);                      \
>      >   scall;
>      >
>      >diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/
>     sysv/linux/riscv/vfork.S
>      >index 1e39b7a057..4cf7b5a9d8 100644
>      >--- a/sysdeps/unix/sysv/linux/riscv/vfork.S
>      >+++ b/sysdeps/unix/sysv/linux/riscv/vfork.S
>      >@@ -29,6 +29,7 @@
>      >
>      >       .text
>      > LEAF (__libc_vfork)
>      >+      LPAD
>      >
>      >       li      a0, (CLONE_VFORK | CLONE_VM | SIGCHLD)
>      >       mv      a1, sp
>      >--
>      >2.39.3
>      >
> 



More information about the Libc-alpha mailing list