[PATCH 00/12] Support RISC-V Control Flow Integrifty (CFI)

Jesse Huang jesse.huang@sifive.com
Wed Jun 18 08:42:46 GMT 2025


Hi, 

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 compier 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 prctl 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. ucontext Compatibility Workaround

    Although ucontext is deprecated by POSIX long time ago, we support it for
    backward compatibility. However, we encountered two major issues:

      a) There is currently no kernel interface for allocating new shadow
         stacks in kernel space.
      b) Without storing the SSP base in the kernel's task structure, we cannot
         determine if two SSPs belong to the same shadow stack region.

    As a temporary and UNSAFE workaround, we allocate shadow stacks in user
    space and directly write the SSP during context switches without ANY
    validation.

ABI Breakage Notes
---------

  [1] SSP is appended at the end of 'struct __jmp_buf_internal_tag'.
  [2] For ucontext, SSP is stored in the t3 register (currently unused) 


Thanks,
Jesse Huang

Jesse Huang (12):
  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: Support ucontext under CFI

 configure                                     |  12 +
 configure.ac                                  |   6 +
 elf/elf.h                                     |   5 +
 manual/tunables.texi                          |  22 ++
 sysdeps/riscv/Makefile                        |  13 +-
 sysdeps/riscv/__longjmp.S                     |  31 ++
 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                    |  36 ++
 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/preconfigure                    |   2 +
 sysdeps/riscv/preconfigure.ac                 |   1 +
 sysdeps/riscv/setjmp.S                        |  13 +
 sysdeps/riscv/start.S                         |   7 +
 sysdeps/unix/sysv/linux/riscv/clone.S         |   2 +
 sysdeps/unix/sysv/linux/riscv/dl-cfi.h        | 115 +++++++
 sysdeps/unix/sysv/linux/riscv/getcontext.S    |   6 +
 .../unix/sysv/linux/riscv/include/asm/prctl.h |  48 +++
 sysdeps/unix/sysv/linux/riscv/makecontext.c   |  19 ++
 sysdeps/unix/sysv/linux/riscv/setcontext.S    |  28 ++
 sysdeps/unix/sysv/linux/riscv/swapcontext.S   |  27 +-
 sysdeps/unix/sysv/linux/riscv/sysdep.S        |   1 +
 sysdeps/unix/sysv/linux/riscv/sysdep.h        |  76 +++++
 sysdeps/unix/sysv/linux/riscv/vfork.S         |   1 +
 38 files changed, 1336 insertions(+), 22 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/unix/sysv/linux/riscv/dl-cfi.h
 create mode 100644 sysdeps/unix/sysv/linux/riscv/include/asm/prctl.h

-- 
2.39.3



More information about the Libc-alpha mailing list