[PATCH v2 00/14] Support RISC-V Control Flow Integrifty (CFI)
Jesse Huang
jesse.huang@sifive.com
Wed Jul 23 09:12:25 GMT 2025
Hi Henrich,
Thanks for your question.
For dynamic binaries, the loader performs a check on all dependencies
listed in link_map, and CFI features (SS, LP) will only be enabled
respectively only if property notes present in all of the dependencies.
I have summarized the possible combinations and their behavior here.
1) Binary w/o CFI
No compatibility problem
2) Binary w/ CFI + dependency w/ CFI
CFI will be enabled and should be no problem
3) Binary w/ CFI + dynamic loading library w/o CFI
a. If the mode is always-on (default), dlopen will fail.
b. If the mode is permissive (can be set by glibc tunables),
CFI will be disabled
4) Binary w/ CFI + dependency w/o CFI
CFI will not be enabled because of the dependency check won't pass
The only case that causes problem is attempting to execute shadow stack
instructions on a RVA20 machine, in this case they will be illegal
instructions due to lacking the support of Zimop/Zcmop, but this is
unlikely to happen.
On Tue, Jul 22, 2025 at 4:54 PM Heinrich Schuchardt <
heinrich.schuchardt@canonical.com> wrote:
> On 11.07.25 15:52, Jesse Huang wrote:
> > This patch series adds support for the new RISC-V Control Flow Integrity
> (CFI)
> > extensions, i.e. Zicfilp and Zicfiss, as described in the following
> sections
> > of the RISC-V Instruction Set Manual:
> >
> > - Volume I, Chapter 33
> > - Volume II, Chapter 22
> >
> > Our implementation largely refers to the existing x86 CET code, and we
> would
> > like to thank the developers for their work.
> >
> > Summary of Changes
> > ------------------
> >
> > 1) New Option for the Build System
> >
> > A new '--enable-cfi' configure option is introduced to control
> whether
> > CFI-related features are enabled. It appends the
> '-fcf-protection=full'
> > compiler flag to all source files.
> >
> > 2) Adjustment to Assembly Code
> >
> > While compiler automatically do the job for C source files,
> assembly files
> > and routines are requiring manual modifications
> > - Insert GNU property notes and landing pad, label setting
> instructions
> > into assembly files and routines
> > - Replace indirect branches with software-guarded branches where
> applicable
> > - Extend setjmp/longjmp to support for the shadow stack by
> appending the
> > shadow stack pointer (SSP) to the jump buffer [1], and handling
> the
> > save/restore/unwinding logic
> >
> > 3) Parse GNU Property Notes and Setup the Environment
> >
> > The loader scans the GNU_PROPERTY_RISCV_FEATURE_1_AND note and
> parses the
> > bits specified by the binary to determine the required CFI
> features, it
> > then performs checks on all dependencies, and uses new prctl
> operations
> > to call to the kernel to do the setup work.
> >
> > 4) Add Tunables for Overriding Runtime Behavior
> >
> > Two new tunables are introduced:
> > - glibc.cpu.riscv_cfi_lp
> > - glibc.cpu.riscv_cfi_ss
> >
> > These control landing pad and shadow stack behavior at runtime,
> > respectively. Each accepts 'on|permissive|off' for its value, which
> is
> > same as x86.
> >
> > 5. Store shadow stack information in TLS to support ucontext
> >
> > We make the following structure changes to support the ucontext
> library
> > - A new helper function `__allocate_shadow_stack` to map a new
> shadow stack
> > Shadow stack size for the new context is based on an estimation
> from the
> > runtime stack size, which is same to the implementation of x86.
> > - Store ssp and shadow stack base marker in TLS
> > - Shrink the _SIGSET_NWORDS from 1024 to 896 for RISC-V to make two
> 8-byte
> > slots for storing ssp and shadow stack base in ucontext_t
> >
> > Differences from V1
> > --------------------
> > - The new option '--enable-cfi' gets a descrition in install.texi and an
> entry
> > in NEWS
> > - Update prctl numbers of landing pad
> > - Re-implement ucontext using shadow stack restore token techniques
> > - Change makecontext to use the `map_shadow_stack` syscall
> >
> > ABI Breakage Notes
> > --------------------
> >
> > [1] SSP is appended at the end of 'struct __jmp_buf_internal_tag'.
> >
> >
> > Thanks,
> > Jesse Huang
> >
> > Jesse Huang (14):
> > riscv: Add --enable-cfi option for controlling cfi features
> > riscv/cfi: Setup necessary options for enable-cfi option
> > riscv: Add GNU property definitions for RISC-V CFI
> > riscv: Adjust assembly routines to support landing pad
> > riscv: Introduce feature variables for holding RISC-V GNU properties
> > riscv/cfi: Add prctl definitions for RISC-V CFI
> > riscv/cfi: Enable CFI on static binaries
> > riscv/cfi: Enable CFI on dynamic binaries
> > riscv/cfi: introduce tunables for CFI features
> > riscv/cfi: Adjust setjmp/longjmp for shadow stack to work
> > riscv/cfi: Support locking/disabling CFI and move OS depedent code
> > riscv/cfi: Store shadow stack information in TLS and ucontext_t
> > riscv/cfi: Add __allocate_shadow_stack for mapping new shadow stack
> > riscv/cfi: Support ucontext under CFI
> >
> > INSTALL | 13 +
> > NEWS | 3 +
> > configure | 12 +
> > configure.ac | 6 +
> > elf/elf.h | 5 +
> > manual/install.texi | 12 +
> > manual/tunables.texi | 22 ++
> > sysdeps/riscv/Makefile | 13 +-
> > sysdeps/riscv/__longjmp.S | 29 ++
> > sysdeps/riscv/bits/setjmp.h | 4 +
> > sysdeps/riscv/cpu-features.c | 46 +++
> > sysdeps/riscv/cpu-tunables.c | 50 +++
> > sysdeps/riscv/crti.S | 4 +
> > sysdeps/riscv/crtn.S | 4 +
> > sysdeps/riscv/dl-cfi.c | 317 ++++++++++++++++++
> > sysdeps/riscv/dl-get-cpu-features.c | 27 ++
> > sysdeps/riscv/dl-machine.h | 35 ++
> > sysdeps/riscv/dl-procruntime.c | 77 +++++
> > sysdeps/riscv/dl-prop.h | 74 ++++
> > sysdeps/riscv/dl-trampoline.S | 61 ++--
> > sysdeps/riscv/dl-tunables.list | 27 ++
> > sysdeps/riscv/feature-control.h | 42 +++
> > sysdeps/riscv/features-offsets.sym | 5 +
> > sysdeps/riscv/ldsodefs.h | 1 +
> > sysdeps/riscv/libc-start.c | 31 ++
> > sysdeps/riscv/libc-start.h | 95 ++++++
> > sysdeps/riscv/link_map.h | 22 ++
> > sysdeps/riscv/multiarch/memcpy_noalignment.S | 4 +
> > sysdeps/riscv/nptl/Makefile | 1 +
> > sysdeps/riscv/nptl/tcb-offsets.sym | 5 +
> > sysdeps/riscv/nptl/tls.h | 2 +
> > sysdeps/riscv/preconfigure | 2 +
> > sysdeps/riscv/preconfigure.ac | 1 +
> > sysdeps/riscv/setjmp.S | 13 +
> > sysdeps/riscv/start.S | 10 +
> > sysdeps/unix/sysv/linux/riscv/Makefile | 1 +
> > .../sysv/linux/riscv/allocate-shadow-stack.c | 55 +++
> > .../sysv/linux/riscv/allocate-shadow-stack.h | 24 ++
> > sysdeps/unix/sysv/linux/riscv/bits/mman.h | 30 ++
> > .../sysv/linux/riscv/bits/types/__sigset_t.h | 13 +
> > sysdeps/unix/sysv/linux/riscv/clone.S | 2 +
> > sysdeps/unix/sysv/linux/riscv/dl-cfi.h | 115 +++++++
> > sysdeps/unix/sysv/linux/riscv/getcontext.S | 20 ++
> > .../unix/sysv/linux/riscv/include/asm/prctl.h | 48 +++
> > sysdeps/unix/sysv/linux/riscv/makecontext.c | 18 +
> > sysdeps/unix/sysv/linux/riscv/setcontext.S | 67 ++++
> > sysdeps/unix/sysv/linux/riscv/swapcontext.S | 77 ++++-
> > sysdeps/unix/sysv/linux/riscv/sys/ucontext.h | 7 +-
> > sysdeps/unix/sysv/linux/riscv/sysdep.S | 1 +
> > sysdeps/unix/sysv/linux/riscv/sysdep.h | 73 ++++
> > sysdeps/unix/sysv/linux/riscv/ucontext_i.sym | 2 +
> > sysdeps/unix/sysv/linux/riscv/vfork.S | 1 +
> > 52 files changed, 1606 insertions(+), 23 deletions(-)
> > create mode 100644 sysdeps/riscv/cpu-features.c
> > create mode 100644 sysdeps/riscv/cpu-tunables.c
> > create mode 100644 sysdeps/riscv/crti.S
> > create mode 100644 sysdeps/riscv/crtn.S
> > create mode 100644 sysdeps/riscv/dl-cfi.c
> > create mode 100644 sysdeps/riscv/dl-get-cpu-features.c
> > create mode 100644 sysdeps/riscv/dl-procruntime.c
> > create mode 100644 sysdeps/riscv/dl-prop.h
> > create mode 100644 sysdeps/riscv/dl-tunables.list
> > create mode 100644 sysdeps/riscv/feature-control.h
> > create mode 100644 sysdeps/riscv/features-offsets.sym
> > create mode 100644 sysdeps/riscv/libc-start.c
> > create mode 100644 sysdeps/riscv/libc-start.h
> > create mode 100644 sysdeps/riscv/link_map.h
> > create mode 100644 sysdeps/riscv/nptl/Makefile
> > create mode 100644 sysdeps/riscv/nptl/tcb-offsets.sym
> > create mode 100644
> sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.c
> > create mode 100644
> sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.h
> > create mode 100644 sysdeps/unix/sysv/linux/riscv/bits/mman.h
> > create mode 100644
> sysdeps/unix/sysv/linux/riscv/bits/types/__sigset_t.h
> > create mode 100644 sysdeps/unix/sysv/linux/riscv/dl-cfi.h
> > create mode 100644 sysdeps/unix/sysv/linux/riscv/include/asm/prctl.h
> >
>
> Hello Jesse,
>
> On riscv64 we must expect that both RVA20 and RVA23 exist. Some of it
> compiled with support with shadow stack some without.
>
> For example maintainers of flatpaks and snaps cannot be expected to
> maintain multiple versions of their packages.
>
> For distros treating support for control flow integrity as a completely
> new architecture is not an attractive solution.
>
> Could you, please, describe how your patch series will ensure the
> interoperability of RVA20 and RVA23 code and of code compiled with and
> without shadow stack.
>
> Best regards
>
> Heinrich
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20250723/ae235286/attachment-0001.htm>
More information about the Libc-alpha
mailing list