#include <asm/vector.h>
#include <asm/vendor_extensions.h>
#include <asm/vendor_extensions/thead.h>
+#include <asm/usercfi.h>
#define NUM_ALPHA_EXTS ('z' - 'a' + 1)
static int riscv_cfilp_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
- if (!IS_ENABLED(CONFIG_RISCV_USER_CFI))
+ if (!IS_ENABLED(CONFIG_RISCV_USER_CFI) ||
+ (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI))
return -EINVAL;
return 0;
static int riscv_cfiss_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
- if (!IS_ENABLED(CONFIG_RISCV_USER_CFI))
+ if (!IS_ENABLED(CONFIG_RISCV_USER_CFI) ||
+ (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI))
return -EINVAL;
return 0;
#include <asm/csr.h>
#include <asm/usercfi.h>
+unsigned long riscv_nousercfi __read_mostly;
+
#define SHSTK_ENTRY_SIZE sizeof(void *)
bool is_shstk_enabled(struct task_struct *task)
void set_shstk_status(struct task_struct *task, bool enable)
{
- if (!cpu_supports_shadow_stack())
+ if (!is_user_shstk_enabled())
return;
task->thread_info.user_cfi_state.ubcfi_en = enable ? 1 : 0;
void set_indir_lp_status(struct task_struct *task, bool enable)
{
- if (!cpu_supports_indirect_br_lp_instr())
+ if (!is_user_lpad_enabled())
return;
task->thread_info.user_cfi_state.ufcfi_en = enable ? 1 : 0;
bool set_tok = flags & SHADOW_STACK_SET_TOKEN;
unsigned long aligned_size = 0;
- if (!cpu_supports_shadow_stack())
+ if (!is_user_shstk_enabled())
return -EOPNOTSUPP;
/* Anything other than set token should result in invalid param */
unsigned long addr, size;
/* If shadow stack is not supported, return 0 */
- if (!cpu_supports_shadow_stack())
+ if (!is_user_shstk_enabled())
return 0;
/*
{
unsigned long base = 0, size = 0;
/* If shadow stack is not supported or not enabled, nothing to release */
- if (!cpu_supports_shadow_stack() || !is_shstk_enabled(tsk))
+ if (!is_user_shstk_enabled() || !is_shstk_enabled(tsk))
return;
/*
{
unsigned long bcfi_status = 0;
- if (!cpu_supports_shadow_stack())
+ if (!is_user_shstk_enabled())
return -EINVAL;
/* this means shadow stack is enabled on the task */
unsigned long size = 0, addr = 0;
bool enable_shstk = false;
- if (!cpu_supports_shadow_stack())
+ if (!is_user_shstk_enabled())
return -EINVAL;
/* Reject unknown flags */
unsigned long arg)
{
/* If shtstk not supported or not enabled on task, nothing to lock here */
- if (!cpu_supports_shadow_stack() ||
+ if (!is_user_shstk_enabled() ||
!is_shstk_enabled(task) || arg != 0)
return -EINVAL;
{
unsigned long fcfi_status = 0;
- if (!cpu_supports_indirect_br_lp_instr())
+ if (!is_user_lpad_enabled())
return -EINVAL;
/* indirect branch tracking is enabled on the task or not */
{
bool enable_indir_lp = false;
- if (!cpu_supports_indirect_br_lp_instr())
+ if (!is_user_lpad_enabled())
return -EINVAL;
/* indirect branch tracking is locked and further can't be modified by user */
* If indirect branch tracking is not supported or not enabled on task,
* nothing to lock here
*/
- if (!cpu_supports_indirect_br_lp_instr() ||
+ if (!is_user_lpad_enabled() ||
!is_indir_lp_enabled(task) || arg != 0)
return -EINVAL;
return 0;
}
+
+bool is_user_shstk_enabled(void)
+{
+ return (cpu_supports_shadow_stack() &&
+ !(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI));
+}
+
+bool is_user_lpad_enabled(void)
+{
+ return (cpu_supports_indirect_br_lp_instr() &&
+ !(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI));
+}
+
+static int __init setup_global_riscv_enable(char *str)
+{
+ if (strcmp(str, "all") == 0)
+ riscv_nousercfi = CMDLINE_DISABLE_RISCV_USERCFI;
+
+ if (strcmp(str, "fcfi") == 0)
+ riscv_nousercfi |= CMDLINE_DISABLE_RISCV_USERCFI_FCFI;
+
+ if (strcmp(str, "bcfi") == 0)
+ riscv_nousercfi |= CMDLINE_DISABLE_RISCV_USERCFI_BCFI;
+
+ if (riscv_nousercfi)
+ pr_info("RISC-V user CFI disabled via cmdline - shadow stack status : %s, landing pad status : %s\n",
+ (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI) ? "disabled" :
+ "enabled", (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI) ?
+ "disabled" : "enabled");
+
+ return 1;
+}
+
+__setup("riscv_nousercfi=", setup_global_riscv_enable);