Skip to content

Support RISC-V Control Flow Integrity Extensions#3

Open
jaidTw wants to merge 14 commits intomasterfrom
enable-cfi
Open

Support RISC-V Control Flow Integrity Extensions#3
jaidTw wants to merge 14 commits intomasterfrom
enable-cfi

Conversation

@jaidTw
Copy link

@jaidTw jaidTw commented May 26, 2025

No description provided.

@jaidTw jaidTw requested a review from kito-cheng May 26, 2025 07:59
Copy link
Member

@kito-cheng kito-cheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you rename most variable about lp to lp_unlabeled since we will have lp_func_sig in future.

@jaidTw jaidTw force-pushed the enable-cfi branch 4 times, most recently from 25abf21 to 78c1733 Compare May 29, 2025 14:41
@jaidTw jaidTw force-pushed the enable-cfi branch 2 times, most recently from 7fae5b2 to b752f71 Compare June 16, 2025 07:40
This tunable is specific to aarch64.
@end deftp

@deftp Tunable glibc.cpu.riscv_cfi_lp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@deftp Tunable glibc.cpu.riscv_cfi_lp
@deftp Tunable glibc.cpu.riscv_cfi_unlabeled_lp


struct dl_riscv_feature_control
{
enum dl_riscv_cfi_control lp : 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum dl_riscv_cfi_control lp : 2;
enum dl_riscv_cfi_control unlabeled_lp : 2;

@jaidTw jaidTw force-pushed the enable-cfi branch 3 times, most recently from 6cb15b3 to fbbc3b0 Compare June 17, 2025 17:02
@jaidTw jaidTw force-pushed the enable-cfi branch 2 times, most recently from 33dc279 to 337c0b3 Compare July 3, 2025 13:37
@jaidTw jaidTw force-pushed the enable-cfi branch 3 times, most recently from 0a049e1 to 6d561c5 Compare July 11, 2025 13:21
jaidTw and others added 13 commits July 11, 2025 06:34
Co-authored-by: Hau Hsu <hau.hsu@sifive.com>
Add GNU properties used by RISC-V CFI extensions (zicfilp/zicfiss)
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>
Co-authored-by: Kito Cheng <kito.cheng@sifive.com>
Member l_riscv_feature_1_and is added to struct link_map, which stores
the feature_1_and property information for each object.

New global _dl_riscv_feature_1 will be used to store what features are
finally enabled for this process.
These operations are for setting/retrieving/locking the status of the
landing pad and the shadow stack extensions.
For static binaries, CFI are enabled inside ARCH_SETUP_TLS, with a macro
to enable the shadow stack to prevent underflowing the shadow stack on
return, and with a function _dl_cfi_setup_features to enable landing
pad.

It scans backward of the program header to find the PT_GNU_PROPERTY note
first, then enable CFI features corresponding to the feature bits.

Co-authored-by: Deepak Gupta <debug@rivosinc.com>
For dynamic binaries, CFI features are parsed from GNU properties, store
in to GLRO(dl_riscv_feature_1) and later enabled in RTLD_START.

Co-authored-by: Deepak Gupta <debug@rivosinc.com>
dl_riscv_feature_control is a structure with each member represents a
feature configuration. At this time it's only used by CFI features.

Each cfi feature is a 2-bit enum, which could be [on|off|permissive],
these values decide whether a new legacy object should be blocked
while loaded dynamically, and could be controled by glibc tunables.
Since longjmp to a previous setjmp'ed state could change the stack
frame and involves stack frame unwinding, shadow stacks is also required
to be unwinded.

The unwinding is implemented according to the zicfiss spec by increasing
the ssp by a page size (4K) at most, to prevent from accidentally point
to another legal shadow stack page after the adjustment.
Switching between different ucontexts involves two cases, one is both
sharing a same shadow stack, which requires a unwinding, and the other
is both using a different shadow stack, which require a stack switch
using shadow stack restore token.

By storing shadow stack in ucontext_t and TLS, we can tell the difference
and perform the following action.
This patch adds support for shadow stack and landing pad to the
ucontext library, shadow stack switches are protected by a shadow stack
restore token which will be validated during the switch.

Co-authored-by: Nia Su <nia.su@sifive.com>
jaidTw pushed a commit that referenced this pull request Feb 6, 2026
On x86-64, when glibc is configured with --enable-stack-protector=all
and compiled with -Os, ld.so crashes very early:

(gdb) r --direct
Starting program: /export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/string/test-memswap --direct

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f41b0a in bsearch (__key=__key@entry=0x7fffffffda28,
    __base=__base@entry=0x7ffff7fca140 <intel_02_known>,
    __nmemb=__nmemb@entry=68, __size=__size@entry=8,
    __compar=__compar@entry=0x7ffff7f3b691 <intel_02_known_compare>)
    at ../bits/stdlib-bsearch.h:22
22	{
(gdb) disass
Dump of assembler code for function bsearch:
   0x00007ffff7f41af0 <+0>:	push   %r15
   0x00007ffff7f41af2 <+2>:	mov    %rcx,%r15
   0x00007ffff7f41af5 <+5>:	push   %r14
   0x00007ffff7f41af7 <+7>:	push   %r13
   0x00007ffff7f41af9 <+9>:	mov    %rsi,%r13
   0x00007ffff7f41afc <+12>:	push   %r12
   0x00007ffff7f41afe <+14>:	mov    %rdi,%r12
   0x00007ffff7f41b01 <+17>:	push   %rbp
   0x00007ffff7f41b02 <+18>:	mov    %rdx,%rbp
   0x00007ffff7f41b05 <+21>:	push   %rbx
   0x00007ffff7f41b06 <+22>:	sub    $0x18,%rsp
=> 0x00007ffff7f41b0a <+26>:	mov    %fs:0x28,%r14
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We can't use stack protector at this point.
   0x00007ffff7f41b13 <+35>:	mov    %r14,0x8(%rsp)
   0x00007ffff7f41b18 <+40>:	mov    %r8,%r14
   0x00007ffff7f41b1b <+43>:	test   %rbp,%rbp
   0x00007ffff7f41b1e <+46>:	je     0x7ffff7f41b48 <bsearch+88>
   0x00007ffff7f41b20 <+48>:	mov    %rbp,%rbx
   0x00007ffff7f41b23 <+51>:	mov    %r12,%rdi
   0x00007ffff7f41b26 <+54>:	shr    $1,%rbx
   0x00007ffff7f41b29 <+57>:	imul   %r15,%rbx
   0x00007ffff7f41b2d <+61>:	add    %r13,%rbx
   0x00007ffff7f41b30 <+64>:	mov    %rbx,%rsi
(gdb) bt
 #0  0x00007ffff7f41b0a in bsearch (__key=__key@entry=0x7fffffffda28,
    __base=__base@entry=0x7ffff7fca140 <intel_02_known>,
    __nmemb=__nmemb@entry=68, __size=__size@entry=8,
    __compar=__compar@entry=0x7ffff7f3b691 <intel_02_known_compare>)
    at ../bits/stdlib-bsearch.h:22
 #1  0x00007ffff7f3c1be in intel_check_word (name=188, value=1979933440,
    has_level_2=has_level_2@entry=0x7fffffffda7f,
    no_level_2_or_3=no_level_2_or_3@entry=0x7fffffffda7e,
    cpu_features=<optimized out>) at ../sysdeps/x86/dl-cacheinfo.h:217
 #2  0x00007ffff7f3c29f in handle_intel (name=name@entry=188,
    cpu_features=<optimized out>) at ../sysdeps/x86/dl-cacheinfo.h:279
 #3  0x00007ffff7f3ccf9 in dl_init_cacheinfo (cpu_features=<optimized out>)
    at ../sysdeps/x86/dl-cacheinfo.h:852
 riscvarchive#4  init_cpu_features (cpu_features=<optimized out>)
    at ../sysdeps/x86/cpu-features.c:1153
 riscvarchive#5  0x00007ffff7f3d6f9 in __libc_start_main_impl (main=0x7ffff7f396dc <main>,
    argc=2, argv=0x7fffffffdbe8, init=<optimized out>, fini=<optimized out>,
    rtld_fini=0x0, stack_end=0x7fffffffdbd8) at ../csu/libc-start.c:269
 riscvarchive#6  0x00007ffff7f39901 in _start () at ../sysdeps/x86_64/start.S:115
(gdb)

The problem is that since __USE_EXTERN_INLINES isn't defined with -Os,
the inline bsearch in <bits/stdlib-bsearch.h> isn't available and the
external bsearch is compiled with stack protector.  Include
<bits/stdlib-bsearch.h> in dl-cacheinfo.h fixed BZ #33374.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants