Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ passed to 'configure'. For example:

NOTE: '--enable-cet' is only supported on x86_64 and x32.

'--enable-cfi'
Enable RISC-V Control Flow Integrity Extensions (Zicfilp/Zicfiss)
support. When the GNU C Library is built with '--enable-cfi', the
resulting library is protected with landing pad and shadow stack.
This feature is currently supported on RV64 with GCC 15 and
binutils 2.45 or later. With '--enable-cfi', it is an error to
dlopen a non CFI enabled shared library in CFI enabled application.
The restriction can be loosen by setting to permissive mode with
the use of the glibc tunables, see glibc tunables section for more
information.

NOTE: '--enable-cfi' is only supported on RV64.

'--enable-memory-tagging'
Enable memory tagging support if the architecture supports it.
When the GNU C Library is built with this option then the resulting
Expand Down
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Major new features:
* The ISO C2Y family of unsigned abs functions, i.e.
uabs, ulabs, ullabs and uimaxabs, are now supported.

* Added --enable-cfi option to enable the RISC-V CFI extensions
(Zicfilp/Zicfiss) support on RV64 Linux.

Deprecated and removed features, and other changes affecting compatibility:

* The glibc.rtld.execstack now supports a compatibility mode to allow
Expand Down
12 changes: 12 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@ enable_nscd
enable_pt_chown
enable_mathvec
enable_cet
enable_cfi
enable_scv
enable_fortify_source
with_cpu
Expand Down Expand Up @@ -1499,6 +1500,7 @@ Optional Features:
depends on architecture]
--enable-cet enable Intel Control-flow Enforcement Technology
(CET), x86 only
--enable-cfi enable Control Flow Integrity (CFI), RISC-V only
--disable-scv syscalls will not use scv instruction, even if the
kernel supports it, powerpc only
--enable-fortify-source[=1|2|3]
Expand Down Expand Up @@ -4853,6 +4855,16 @@ esac
fi


# Check whether --enable-cfi was given.
if test ${enable_cfi+y}
then :
enableval=$enable_cfi; enable_cfi=$enableval
else case e in #(
e) enable_cfi=no ;;
esac
fi


# Check whether --enable-scv was given.
if test ${enable_scv+y}
then :
Expand Down
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ AC_ARG_ENABLE([cet],
[enable_cet=$enableval],
[enable_cet=$libc_cv_compiler_default_cet])

AC_ARG_ENABLE([cfi],
AS_HELP_STRING([--enable-cfi],
[enable Control Flow Integrity (CFI), RISC-V only]),
[enable_cfi=$enableval],
[enable_cfi=no])

AC_ARG_ENABLE([scv],
AS_HELP_STRING([--disable-scv],
[syscalls will not use scv instruction, even if the kernel supports it, powerpc only]),
Expand Down
5 changes: 5 additions & 0 deletions elf/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,11 @@ typedef struct
SHSTK. */
#define GNU_PROPERTY_X86_FEATURE_1_SHSTK (1U << 1)

/* RISC-V specific GNU PROPERTY. */
#define GNU_PROPERTY_RISCV_FEATURE_1_AND 0xc0000000
#define GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED (1u << 0)
#define GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS (1u << 1)

/* Move records. */
typedef struct
{
Expand Down
12 changes: 12 additions & 0 deletions manual/install.texi
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ non CET enabled shared library in CET enabled application.

NOTE: @option{--enable-cet} is only supported on x86_64 and x32.

@item --enable-cfi
Enable RISC-V Control Flow Integrity Extensions (Zicfilp/Zicfiss) support.
When @theglibc{} is built with @option{--enable-cfi}, the resulting
library is protected with landing pad and shadow stack@.
This feature is currently supported on RV64 with GCC 15 and binutils 2.45
or later. With @option{--enable-cfi}, it is an error to dlopen a non CFI
enabled shared library in CFI enabled application. The restriction can be
loosen by setting to permissive mode with the use of the glibc tunables,
see glibc tunables section for more information.

NOTE: @option{--enable-cfi} is only supported on RV64.

@item --enable-memory-tagging
Enable memory tagging support if the architecture supports it. When
@theglibc{} is built with this option then the resulting library will
Expand Down
22 changes: 22 additions & 0 deletions manual/tunables.texi
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,28 @@ assume that the CPU is @code{xxx} where xxx may have one of these values:
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

The @code{glibc.cpu.riscv_cfi_lp=[on|off|permissive]} tunable allows the
user to temporarily turn off the branch control flow protection (a.k.a.
landing pad) or set to permissive mode. The default value is @code{on} for
target compiled with Zicfilp extension. Permissive mode allows the protection
to be turned off on program trying to dynamically load a legacy shared library
without landing pad support.

This tunable is specific to riscv.
@end deftp

@deftp Tunable glibc.cpu.riscv_cfi_ss
The @code{glibc.cpu.riscv_cfi_ss=[on|off|permissive]} tunable allows the
user to temporarily turn off the return control flow protection (a.k.a.
shadow stack) or set to permissive mode. The default value is @code{on} for
target compiled with Zicfiss extension. Permissive mode allows the protection
to be turned off on program trying to dynamically load a legacy shared library
without shadow stack support.

This tunable is specific to riscv.
@end deftp

@deftp Tunable glibc.cpu.x86_data_cache_size
The @code{glibc.cpu.x86_data_cache_size} tunable allows the user to set
data cache size in bytes for use in memory and string routines.
Expand Down
13 changes: 12 additions & 1 deletion sysdeps/riscv/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
ifeq ($(subdir),misc)
sysdep_headers += sys/asm.h
endif
sysdep-dl-routines += dl-get-cpu-features

ifeq ($(subdir),elf)
gen-as-const-headers += dl-link.sym
gen-as-const-headers += dl-link.sym features-offsets.sym
endif

# RISC-V's assembler also needs to know about PIC as it changes the definition
Expand All @@ -15,3 +16,13 @@ ASFLAGS-.os += -Wa,-mno-relax
ASFLAGS-.o += -Wa,-mno-relax
sysdep-CFLAGS += -mno-relax
endif

# Enable RISC-V CFI
ifeq (yes,$(riscv-enable-cfi))
sysdep-dl-routines += dl-cfi
CFLAGS-.o += -fcf-protection=full
CFLAGS-.os += -fcf-protection=full
CFLAGS-.op += -fcf-protection=full
CFLAGS-.oS += -fcf-protection=full
asm-CPPFLAGS += -fcf-protection=full -include sysdep.h
endif
29 changes: 29 additions & 0 deletions sysdeps/riscv/__longjmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -50,6 +51,34 @@ ENTRY (__longjmp)
FREG_L fs11,14*SZREG+11*SZFREG(a0)
#endif

#ifdef __riscv_shadow_stack
/* skip unwinding if ss is not enabled */
ssrdp t0
beqz t0, .Lunwind_fin
# ifndef __riscv_float_abi_soft
REG_L t1, 14*SZREG+12*SZFREG(a0)
# else
REG_L t1, 14*SZREG(a0)
# endif
.Lunwind:
bleu t1, t0, .Lunwind_fin
/* Increase ssp by at most a page size to ensure always run into a
guard page before accidentally point to another legal shadow stack
page */
/* t0 = (t1 - t0 >= 4096) ? t0 + 4096 : t1 */
lui a0, 1
add t0, t0, a0
bleu t0, t1, 1f
mv t0, t1
1:
csrw ssp, t0
/* Test if the location pointed by ssp is legal */
sspush x5
sspopchk x5
j .Lunwind
.Lunwind_fin:
#endif

seqz a0, a1
add a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
ret
Expand Down
4 changes: 4 additions & 0 deletions sysdeps/riscv/bits/setjmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ typedef struct __jmp_buf_internal_tag
double __fpregs[12];
#elif !defined __riscv_float_abi_soft
# error unsupported FLEN
#endif
#ifdef __riscv_shadow_stack
/* Shadow stack pointer. */
long int __ssp;
#endif
} __jmp_buf[1];

Expand Down
46 changes: 46 additions & 0 deletions sysdeps/riscv/cpu-features.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* Initialize CPU feature data.
This file is part of the GNU C Library.
Copyright (C) 2025 Free Software Foundation, Inc.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#ifndef _CPU_FEATURES_RISCV_H
#define _CPU_FEATURES_RISCV_H

# define TUNABLE_NAMESPACE cpu
# include <cpu-tunables.c>

# ifdef __riscv_landing_pad
extern void TUNABLE_CALLBACK (set_riscv_cfi_lp) (tunable_val_t *)
attribute_hidden;
# endif
# ifdef __riscv_shadow_stack
extern void TUNABLE_CALLBACK (set_riscv_cfi_ss) (tunable_val_t *)
attribute_hidden;
# endif

static inline void
init_cpu_features (void)
{
# ifdef __riscv_landing_pad
TUNABLE_GET (riscv_cfi_lp, tunable_val_t *,
TUNABLE_CALLBACK (set_riscv_cfi_lp));
# endif
# ifdef __riscv_shadow_stack
TUNABLE_GET (riscv_cfi_ss, tunable_val_t *,
TUNABLE_CALLBACK (set_riscv_cfi_ss));
# endif
}
#endif /* _CPU_FEATURES_RISCV_H */
50 changes: 50 additions & 0 deletions sysdeps/riscv/cpu-tunables.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* RISC-V CPU feature tuning.
This file is part of the GNU C Library.
Copyright (C) 2025 Free Software Foundation, Inc.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#define TUNABLE_NAMESPACE cpu
#include <elf/dl-tunables.h>
#include <dl-tunables-parse.h>
#include <ldsodefs.h>

#ifdef __riscv_landing_pad
attribute_hidden
void
TUNABLE_CALLBACK (set_riscv_cfi_lp) (tunable_val_t *valp)
{
if (tunable_strcmp_cte (valp, "permissive"))
GL(dl_riscv_feature_control).lp = cfi_permissive;
else if (tunable_strcmp_cte (valp, "off"))
GL(dl_riscv_feature_control).lp = cfi_always_off;
else
GL(dl_riscv_feature_control).lp = cfi_always_on;
}
#endif

#ifdef __riscv_shadow_stack
attribute_hidden
void
TUNABLE_CALLBACK (set_riscv_cfi_ss) (tunable_val_t *valp)
{
if (tunable_strcmp_cte (valp, "permissive"))
GL(dl_riscv_feature_control).ss = cfi_permissive;
else if (tunable_strcmp_cte (valp, "off"))
GL(dl_riscv_feature_control).ss = cfi_always_off;
else
GL(dl_riscv_feature_control).ss = cfi_always_on;
}
#endif
4 changes: 4 additions & 0 deletions sysdeps/riscv/crti.S
Original file line number Diff line number Diff line change
@@ -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>
4 changes: 4 additions & 0 deletions sysdeps/riscv/crtn.S
Original file line number Diff line number Diff line change
@@ -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>
Loading