On 11/17/25 1:12 PM, Kees Cook wrote:
Implement RISC-V-specific KCFI backend. Nothing is conceptually rv64
specific, but using an alternative set of instructions for rv32 would be
needed, and at present the only user of KCFI on riscv is the rv64 build
of the Linux kernel.
- Scratch register allocation using t1/t2 (x6/x7) following RISC-V
procedure call standard for temporary registers (already
caller-saved), and t3 (x8) when either t1 or t2 is already the call
target register.
- Incompatible with -ffixed-t1, -ffixed-t2, or -ffixed-t3.
- Integration with .kcfi_traps section for debugger/runtime metadata
(like x86_64).
Assembly Code Pattern for RISC-V:
lw t1, -4(target_reg) ; Load actual type ID from preamble
lui t2, %hi(expected_type) ; Load expected type (upper 20 bits)
addiw t2, t2, %lo(expected_type) ; Add lower 12 bits (sign-extended)
beq t1, t2, .Lkcfi_call ; Branch if types match
.Lkcfi_trap: ebreak ; Environment break trap on mismatch
.Lkcfi_call: jalr/jr target_reg ; Execute validated indirect transfer
Build and run tested with Linux kernel ARCH=riscv.
gcc/ChangeLog:
config/riscv/riscv-protos.h: Declare KCFI helpers.
config/riscv/riscv.cc (riscv_maybe_wrap_call_with_kcfi): New
function, to wrap calls.
(riscv_maybe_wrap_call_value_with_kcfi): New function, to
wrap calls with return values.
(riscv_output_kcfi_insn): New function to emit KCFI assembly.
config/riscv/riscv.md: Add KCFI RTL patterns and hook expansion.
doc/invoke.texi: Document riscv nuances.
gcc/testsuite/ChangeLog:
* gcc.dg/kcfi/kcfi-adjacency.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-basics.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-call-sharing.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-complex-addressing.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-move-preservation.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-no-sanitize-inline.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-no-sanitize.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-offset-validation.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-patchable-entry-only.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-patchable-large.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-patchable-medium.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-patchable-prefix-only.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-tail-calls.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-trap-section.c: Add riscv patterns.
* gcc.dg/kcfi/kcfi-riscv-fixed-t1.c: New test.
* gcc.dg/kcfi/kcfi-riscv-fixed-t2.c: New test.
* gcc.dg/kcfi/kcfi-riscv-fixed-t3.c: New test.
Note there's still review work to do on the RISC-V bits. But it's worth
noting your patch triggers ICEs in the RISC-V testsuite. See:
https://github.com/ewlu/gcc-precommit-ci/issues/4115#issuecomment-3543758441
Jeff