Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arch/riscv: add dual vdso creation logic and select vdso based on hw

Shadow stack instructions are taken from the Zimop ISA extension,
which is mandated on RVA23. Any userspace with shadow stack
instructions in it will fault on hardware that doesn't have support
for Zimop. Thus, a shadow stack-enabled userspace can't be run on
hardware that doesn't support Zimop.

It's not known how Linux userspace providers will respond to this kind
of binary fragmentation. In order to keep kernel portable across
different hardware, 'arch/riscv/kernel/vdso_cfi' is created which has
Makefile logic to compile 'arch/riscv/kernel/vdso' sources with CFI
flags, and 'arch/riscv/kernel/vdso.c' is modified to select the
appropriate vdso depending on whether the underlying CPU implements
the Zimop extension. Since the offset of vdso symbols will change due
to having two different vdso binaries, there is added logic to include
a new generated vdso offset header and dynamically select the offset
(like for rt_sigreturn).

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Acked-by: Charles Mirabile <cmirabil@redhat.com>
Tested-by: Andreas Korb <andreas.korb@aisec.fraunhofer.de> # QEMU, custom CVA6
Tested-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
Link: https://patch.msgid.link/20251112-v5_user_cfi_series-v23-24-b55691eacf4f@rivosinc.com
[pjw@kernel.org: cleaned up patch description]
Signed-off-by: Paul Walmsley <pjw@kernel.org>

authored by

Deepak Gupta and committed by
Paul Walmsley
ccad8c13 37f57bd3

+82 -11
+3
arch/riscv/Makefile
··· 161 161 prepare: vdso_prepare 162 162 vdso_prepare: prepare0 163 163 $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h 164 + $(if $(CONFIG_RISCV_USER_CFI),$(Q)$(MAKE) \ 165 + $(build)=arch/riscv/kernel/vdso_cfi include/generated/vdso-cfi-offsets.h) 164 166 $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \ 165 167 $(build)=arch/riscv/kernel/compat_vdso include/generated/compat_vdso-offsets.h) 166 168 ··· 170 168 endif 171 169 172 170 vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg 171 + vdso-install-$(CONFIG_RISCV_USER_CFI) += arch/riscv/kernel/vdso_cfi/vdso-cfi.so.dbg 173 172 vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg 174 173 175 174 BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader loader.bin xipImage vmlinuz.efi
+12 -1
arch/riscv/include/asm/vdso.h
··· 18 18 19 19 #ifndef __ASSEMBLER__ 20 20 #include <generated/vdso-offsets.h> 21 + #ifdef CONFIG_RISCV_USER_CFI 22 + #include <generated/vdso-cfi-offsets.h> 23 + #endif 21 24 25 + #ifdef CONFIG_RISCV_USER_CFI 22 26 #define VDSO_SYMBOL(base, name) \ 23 - (void __user *)((unsigned long)(base) + __vdso_##name##_offset) 27 + (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZIMOP) ? \ 28 + (void __user *)((unsigned long)(base) + __vdso_##name##_cfi_offset) : \ 29 + (void __user *)((unsigned long)(base) + __vdso_##name##_offset)) 30 + #else 31 + #define VDSO_SYMBOL(base, name) \ 32 + ((void __user *)((unsigned long)(base) + __vdso_##name##_offset)) 33 + #endif 24 34 25 35 #ifdef CONFIG_COMPAT 26 36 #include <generated/compat_vdso-offsets.h> ··· 43 33 #endif /* CONFIG_COMPAT */ 44 34 45 35 extern char vdso_start[], vdso_end[]; 36 + extern char vdso_cfi_start[], vdso_cfi_end[]; 46 37 47 38 #endif /* !__ASSEMBLER__ */ 48 39
+1
arch/riscv/kernel/Makefile
··· 73 73 obj-y += probes/ 74 74 obj-y += tests/ 75 75 obj-$(CONFIG_MMU) += vdso.o vdso/ 76 + obj-$(CONFIG_RISCV_USER_CFI) += vdso_cfi/ 76 77 77 78 obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o 78 79 obj-$(CONFIG_RISCV_MISALIGNED) += unaligned_access_speed.o
+7
arch/riscv/kernel/vdso.c
··· 98 98 99 99 static int __init vdso_init(void) 100 100 { 101 + /* Hart implements zimop, expose cfi compiled vdso */ 102 + if (IS_ENABLED(CONFIG_RISCV_USER_CFI) && 103 + riscv_has_extension_unlikely(RISCV_ISA_EXT_ZIMOP)) { 104 + vdso_info.vdso_code_start = vdso_cfi_start; 105 + vdso_info.vdso_code_end = vdso_cfi_end; 106 + } 107 + 101 108 __vdso_init(&vdso_info); 102 109 #ifdef CONFIG_COMPAT 103 110 __vdso_init(&compat_vdso_info);
+20 -9
arch/riscv/kernel/vdso/Makefile
··· 20 20 ifdef VDSO_CFI_BUILD 21 21 CFI_MARCH = _zicfilp_zicfiss 22 22 CFI_FULL = -fcf-protection=full 23 + CFI_SUFFIX = -cfi 24 + OFFSET_SUFFIX = _cfi 25 + ccflags-y += -DVDSO_CFI=1 26 + asflags-y += -DVDSO_CFI=1 23 27 endif 24 28 25 29 # Files to link into the vdso ··· 52 48 CFLAGS_hwprobe.o += -fPIC 53 49 54 50 # Build rules 55 - targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds 51 + vdso_offsets := vdso$(if $(VDSO_CFI_BUILD),$(CFI_SUFFIX),)-offsets.h 52 + vdso_o := vdso$(if $(VDSO_CFI_BUILD),$(CFI_SUFFIX),).o 53 + vdso_so := vdso$(if $(VDSO_CFI_BUILD),$(CFI_SUFFIX),).so 54 + vdso_so_dbg := vdso$(if $(VDSO_CFI_BUILD),$(CFI_SUFFIX),).so.dbg 55 + vdso_lds := vdso.lds 56 + 57 + targets := $(obj-vdso) $(vdso_so) $(vdso_so_dbg) $(vdso_lds) 58 + 56 59 obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) 57 60 58 - obj-y += vdso.o 59 - CPPFLAGS_vdso.lds += -P -C -U$(ARCH) 61 + obj-y += vdso$(if $(VDSO_CFI_BUILD),$(CFI_SUFFIX),).o 62 + CPPFLAGS_$(vdso_lds) += -P -C -U$(ARCH) 60 63 ifneq ($(filter vgettimeofday, $(vdso-syms)),) 61 - CPPFLAGS_vdso.lds += -DHAS_VGETTIMEOFDAY 64 + CPPFLAGS_$(vdso_lds) += -DHAS_VGETTIMEOFDAY 62 65 endif 63 66 64 67 # Disable -pg to prevent insert call site ··· 74 63 CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) 75 64 76 65 # Force dependency 77 - $(obj)/vdso.o: $(obj)/vdso.so 66 + $(obj)/$(vdso_o): $(obj)/$(vdso_so) 78 67 79 68 # link rule for the .so file, .lds has to be first 80 - $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE 69 + $(obj)/$(vdso_so_dbg): $(obj)/$(vdso_lds) $(obj-vdso) FORCE 81 70 $(call if_changed,vdsold_and_check) 82 - LDFLAGS_vdso.so.dbg = -shared -soname=linux-vdso.so.1 \ 71 + LDFLAGS_$(vdso_so_dbg) = -shared -soname=linux-vdso.so.1 \ 83 72 --build-id=sha1 --eh-frame-hdr 84 73 85 74 # strip rule for the .so file ··· 90 79 # Generate VDSO offsets using helper script 91 80 gen-vdsosym := $(src)/gen_vdso_offsets.sh 92 81 quiet_cmd_vdsosym = VDSOSYM $@ 93 - cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ 82 + cmd_vdsosym = $(NM) $< | $(gen-vdsosym) $(OFFSET_SUFFIX) | LC_ALL=C sort > $@ 94 83 95 - include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE 84 + include/generated/$(vdso_offsets): $(obj)/$(vdso_so_dbg) FORCE 96 85 $(call if_changed,vdsosym) 97 86 98 87 # actual build commands
+3 -1
arch/riscv/kernel/vdso/gen_vdso_offsets.sh
··· 2 2 # SPDX-License-Identifier: GPL-2.0 3 3 4 4 LC_ALL=C 5 - sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p' 5 + SUFFIX=${1:-""} 6 + sed -n -e \ 7 + 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2'$SUFFIX'_offset\t0x\1/p'
+25
arch/riscv/kernel/vdso_cfi/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # RISC-V VDSO CFI Makefile 3 + # This Makefile builds the VDSO with CFI support when CONFIG_RISCV_USER_CFI is enabled 4 + 5 + # setting VDSO_CFI_BUILD triggers build for vdso differently 6 + VDSO_CFI_BUILD := 1 7 + 8 + # Set the source directory to the main vdso directory 9 + src := $(srctree)/arch/riscv/kernel/vdso 10 + 11 + # Copy all .S and .c files from vdso directory to vdso_cfi object build directory 12 + vdso_c_sources := $(wildcard $(src)/*.c) 13 + vdso_S_sources := $(wildcard $(src)/*.S) 14 + vdso_c_objects := $(addprefix $(obj)/, $(notdir $(vdso_c_sources))) 15 + vdso_S_objects := $(addprefix $(obj)/, $(notdir $(vdso_S_sources))) 16 + 17 + $(vdso_S_objects): $(obj)/%.S: $(src)/%.S 18 + $(Q)cp $< $@ 19 + 20 + $(vdso_c_objects): $(obj)/%.c: $(src)/%.c 21 + $(Q)cp $< $@ 22 + 23 + # Include the main VDSO Makefile which contains all the build rules and sources 24 + # The VDSO_CFI_BUILD variable will be passed to it to enable CFI compilation 25 + include $(src)/Makefile
+11
arch/riscv/kernel/vdso_cfi/vdso-cfi.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright 2025 Rivos, Inc 4 + */ 5 + 6 + #define vdso_start vdso_cfi_start 7 + #define vdso_end vdso_cfi_end 8 + 9 + #define __VDSO_PATH "arch/riscv/kernel/vdso_cfi/vdso-cfi.so" 10 + 11 + #include "../vdso/vdso.S"