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.

riscv: add kernel command line option to opt out of user CFI

Add a kernel command line option to disable part or all
of user CFI. User backward CFI and forward CFI can be controlled
independently. The kernel command line parameter "riscv_nousercfi" can
take the following values:
- "all" : Disable forward and backward cfi both
- "bcfi" : Disable backward cfi
- "fcfi" : Disable forward cfi

Signed-off-by: Deepak Gupta <debug@rivosinc.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-21-b55691eacf4f@rivosinc.com
[pjw@kernel.org: fixed warnings from checkpatch; cleaned up patch description, doc, printk text]
Signed-off-by: Paul Walmsley <pjw@kernel.org>

authored by

Deepak Gupta and committed by
Paul Walmsley
c9b859c4 30c30990

+69 -13
+8
Documentation/admin-guide/kernel-parameters.txt
··· 6606 6606 replacement properties are not found. See the Kconfig 6607 6607 entry for RISCV_ISA_FALLBACK. 6608 6608 6609 + riscv_nousercfi= 6610 + all Disable user CFI ABI to userspace even if cpu extension 6611 + are available. 6612 + bcfi Disable user backward CFI ABI to userspace even if 6613 + the shadow stack extension is available. 6614 + fcfi Disable user forward CFI ABI to userspace even if the 6615 + landing pad extension is available. 6616 + 6609 6617 ro [KNL] Mount root device read-only on boot 6610 6618 6611 6619 rodata= [KNL,EARLY]
+9
arch/riscv/include/asm/usercfi.h
··· 5 5 #ifndef _ASM_RISCV_USERCFI_H 6 6 #define _ASM_RISCV_USERCFI_H 7 7 8 + #define CMDLINE_DISABLE_RISCV_USERCFI_FCFI 1 9 + #define CMDLINE_DISABLE_RISCV_USERCFI_BCFI 2 10 + #define CMDLINE_DISABLE_RISCV_USERCFI 3 11 + 8 12 #ifndef __ASSEMBLER__ 9 13 #include <linux/types.h> 10 14 #include <linux/prctl.h> ··· 16 12 17 13 struct task_struct; 18 14 struct kernel_clone_args; 15 + 16 + extern unsigned long riscv_nousercfi; 19 17 20 18 #ifdef CONFIG_RISCV_USER_CFI 21 19 struct cfi_state { ··· 88 82 #define get_active_shstk(task) 0UL 89 83 90 84 #endif /* CONFIG_RISCV_USER_CFI */ 85 + 86 + bool is_user_shstk_enabled(void); 87 + bool is_user_lpad_enabled(void); 91 88 92 89 #endif /* __ASSEMBLER__ */ 93 90
+5 -2
arch/riscv/kernel/cpufeature.c
··· 28 28 #include <asm/vector.h> 29 29 #include <asm/vendor_extensions.h> 30 30 #include <asm/vendor_extensions/thead.h> 31 + #include <asm/usercfi.h> 31 32 32 33 #define NUM_ALPHA_EXTS ('z' - 'a' + 1) 33 34 ··· 300 299 static int riscv_cfilp_validate(const struct riscv_isa_ext_data *data, 301 300 const unsigned long *isa_bitmap) 302 301 { 303 - if (!IS_ENABLED(CONFIG_RISCV_USER_CFI)) 302 + if (!IS_ENABLED(CONFIG_RISCV_USER_CFI) || 303 + (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI)) 304 304 return -EINVAL; 305 305 306 306 return 0; ··· 310 308 static int riscv_cfiss_validate(const struct riscv_isa_ext_data *data, 311 309 const unsigned long *isa_bitmap) 312 310 { 313 - if (!IS_ENABLED(CONFIG_RISCV_USER_CFI)) 311 + if (!IS_ENABLED(CONFIG_RISCV_USER_CFI) || 312 + (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI)) 314 313 return -EINVAL; 315 314 316 315 return 0;
+47 -11
arch/riscv/kernel/usercfi.c
··· 17 17 #include <asm/csr.h> 18 18 #include <asm/usercfi.h> 19 19 20 + unsigned long riscv_nousercfi __read_mostly; 21 + 20 22 #define SHSTK_ENTRY_SIZE sizeof(void *) 21 23 22 24 bool is_shstk_enabled(struct task_struct *task) ··· 61 59 62 60 void set_shstk_status(struct task_struct *task, bool enable) 63 61 { 64 - if (!cpu_supports_shadow_stack()) 62 + if (!is_user_shstk_enabled()) 65 63 return; 66 64 67 65 task->thread_info.user_cfi_state.ubcfi_en = enable ? 1 : 0; ··· 91 89 92 90 void set_indir_lp_status(struct task_struct *task, bool enable) 93 91 { 94 - if (!cpu_supports_indirect_br_lp_instr()) 92 + if (!is_user_lpad_enabled()) 95 93 return; 96 94 97 95 task->thread_info.user_cfi_state.ufcfi_en = enable ? 1 : 0; ··· 259 257 bool set_tok = flags & SHADOW_STACK_SET_TOKEN; 260 258 unsigned long aligned_size = 0; 261 259 262 - if (!cpu_supports_shadow_stack()) 260 + if (!is_user_shstk_enabled()) 263 261 return -EOPNOTSUPP; 264 262 265 263 /* Anything other than set token should result in invalid param */ ··· 306 304 unsigned long addr, size; 307 305 308 306 /* If shadow stack is not supported, return 0 */ 309 - if (!cpu_supports_shadow_stack()) 307 + if (!is_user_shstk_enabled()) 310 308 return 0; 311 309 312 310 /* ··· 352 350 { 353 351 unsigned long base = 0, size = 0; 354 352 /* If shadow stack is not supported or not enabled, nothing to release */ 355 - if (!cpu_supports_shadow_stack() || !is_shstk_enabled(tsk)) 353 + if (!is_user_shstk_enabled() || !is_shstk_enabled(tsk)) 356 354 return; 357 355 358 356 /* ··· 381 379 { 382 380 unsigned long bcfi_status = 0; 383 381 384 - if (!cpu_supports_shadow_stack()) 382 + if (!is_user_shstk_enabled()) 385 383 return -EINVAL; 386 384 387 385 /* this means shadow stack is enabled on the task */ ··· 395 393 unsigned long size = 0, addr = 0; 396 394 bool enable_shstk = false; 397 395 398 - if (!cpu_supports_shadow_stack()) 396 + if (!is_user_shstk_enabled()) 399 397 return -EINVAL; 400 398 401 399 /* Reject unknown flags */ ··· 448 446 unsigned long arg) 449 447 { 450 448 /* If shtstk not supported or not enabled on task, nothing to lock here */ 451 - if (!cpu_supports_shadow_stack() || 449 + if (!is_user_shstk_enabled() || 452 450 !is_shstk_enabled(task) || arg != 0) 453 451 return -EINVAL; 454 452 ··· 461 459 { 462 460 unsigned long fcfi_status = 0; 463 461 464 - if (!cpu_supports_indirect_br_lp_instr()) 462 + if (!is_user_lpad_enabled()) 465 463 return -EINVAL; 466 464 467 465 /* indirect branch tracking is enabled on the task or not */ ··· 474 472 { 475 473 bool enable_indir_lp = false; 476 474 477 - if (!cpu_supports_indirect_br_lp_instr()) 475 + if (!is_user_lpad_enabled()) 478 476 return -EINVAL; 479 477 480 478 /* indirect branch tracking is locked and further can't be modified by user */ ··· 498 496 * If indirect branch tracking is not supported or not enabled on task, 499 497 * nothing to lock here 500 498 */ 501 - if (!cpu_supports_indirect_br_lp_instr() || 499 + if (!is_user_lpad_enabled() || 502 500 !is_indir_lp_enabled(task) || arg != 0) 503 501 return -EINVAL; 504 502 ··· 506 504 507 505 return 0; 508 506 } 507 + 508 + bool is_user_shstk_enabled(void) 509 + { 510 + return (cpu_supports_shadow_stack() && 511 + !(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI)); 512 + } 513 + 514 + bool is_user_lpad_enabled(void) 515 + { 516 + return (cpu_supports_indirect_br_lp_instr() && 517 + !(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI)); 518 + } 519 + 520 + static int __init setup_global_riscv_enable(char *str) 521 + { 522 + if (strcmp(str, "all") == 0) 523 + riscv_nousercfi = CMDLINE_DISABLE_RISCV_USERCFI; 524 + 525 + if (strcmp(str, "fcfi") == 0) 526 + riscv_nousercfi |= CMDLINE_DISABLE_RISCV_USERCFI_FCFI; 527 + 528 + if (strcmp(str, "bcfi") == 0) 529 + riscv_nousercfi |= CMDLINE_DISABLE_RISCV_USERCFI_BCFI; 530 + 531 + if (riscv_nousercfi) 532 + pr_info("RISC-V user CFI disabled via cmdline - shadow stack status : %s, landing pad status : %s\n", 533 + (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI) ? "disabled" : 534 + "enabled", (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI) ? 535 + "disabled" : "enabled"); 536 + 537 + return 1; 538 + } 539 + 540 + __setup("riscv_nousercfi=", setup_global_riscv_enable);