diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/riscv/include/asm/usercfi.h | 8 | ||||
| -rw-r--r-- | arch/riscv/include/uapi/asm/ptrace.h | 42 | ||||
| -rw-r--r-- | arch/riscv/kernel/process.c | 2 | ||||
| -rw-r--r-- | arch/riscv/kernel/ptrace.c | 22 | ||||
| -rw-r--r-- | arch/riscv/kernel/usercfi.c | 39 |
5 files changed, 58 insertions, 55 deletions
diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h index 7495baae1e3c..f56966edbf5c 100644 --- a/arch/riscv/include/asm/usercfi.h +++ b/arch/riscv/include/asm/usercfi.h @@ -39,7 +39,7 @@ void set_active_shstk(struct task_struct *task, unsigned long shstk_addr); bool is_shstk_enabled(struct task_struct *task); bool is_shstk_locked(struct task_struct *task); bool is_shstk_allocated(struct task_struct *task); -void set_shstk_lock(struct task_struct *task); +void set_shstk_lock(struct task_struct *task, bool lock); void set_shstk_status(struct task_struct *task, bool enable); unsigned long get_active_shstk(struct task_struct *task); int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr); @@ -47,7 +47,7 @@ int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr); bool is_indir_lp_enabled(struct task_struct *task); bool is_indir_lp_locked(struct task_struct *task); void set_indir_lp_status(struct task_struct *task, bool enable); -void set_indir_lp_lock(struct task_struct *task); +void set_indir_lp_lock(struct task_struct *task, bool lock); #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE) @@ -69,7 +69,7 @@ void set_indir_lp_lock(struct task_struct *task); #define is_shstk_allocated(task) false -#define set_shstk_lock(task) do {} while (0) +#define set_shstk_lock(task, lock) do {} while (0) #define set_shstk_status(task, enable) do {} while (0) @@ -79,7 +79,7 @@ void set_indir_lp_lock(struct task_struct *task); #define set_indir_lp_status(task, enable) do {} while (0) -#define set_indir_lp_lock(task) do {} while (0) +#define set_indir_lp_lock(task, lock) do {} while (0) #define restore_user_shstk(tsk, shstk_ptr) -EINVAL diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h index 70a74adad914..3de2b7124aff 100644 --- a/arch/riscv/include/uapi/asm/ptrace.h +++ b/arch/riscv/include/uapi/asm/ptrace.h @@ -132,26 +132,28 @@ struct __sc_riscv_cfi_state { unsigned long ss_ptr; /* shadow stack pointer */ }; -#define PTRACE_CFI_LP_EN_BIT 0 -#define PTRACE_CFI_LP_LOCK_BIT 1 -#define PTRACE_CFI_ELP_BIT 2 -#define PTRACE_CFI_SS_EN_BIT 3 -#define PTRACE_CFI_SS_LOCK_BIT 4 -#define PTRACE_CFI_SS_PTR_BIT 5 - -#define PTRACE_CFI_LP_EN_STATE _BITUL(PTRACE_CFI_LP_EN_BIT) -#define PTRACE_CFI_LP_LOCK_STATE _BITUL(PTRACE_CFI_LP_LOCK_BIT) -#define PTRACE_CFI_ELP_STATE _BITUL(PTRACE_CFI_ELP_BIT) -#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT) -#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT) -#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT) - -#define PRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \ - PTRACE_CFI_LP_LOCK_STATE | \ - PTRACE_CFI_ELP_STATE | \ - PTRACE_CFI_SS_EN_STATE | \ - PTRACE_CFI_SS_LOCK_STATE | \ - PTRACE_CFI_SS_PTR_STATE) +#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT 0 +#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT 1 +#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT 2 +#define PTRACE_CFI_SHADOW_STACK_EN_BIT 3 +#define PTRACE_CFI_SHADOW_STACK_LOCK_BIT 4 +#define PTRACE_CFI_SHADOW_STACK_PTR_BIT 5 + +#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT) +#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE \ + _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT) +#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE \ + _BITUL(PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT) +#define PTRACE_CFI_SHADOW_STACK_EN_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_EN_BIT) +#define PTRACE_CFI_SHADOW_STACK_LOCK_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_LOCK_BIT) +#define PTRACE_CFI_SHADOW_STACK_PTR_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_PTR_BIT) + +#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \ + PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE | \ + PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE | \ + PTRACE_CFI_SHADOW_STACK_EN_STATE | \ + PTRACE_CFI_SHADOW_STACK_LOCK_STATE | \ + PTRACE_CFI_SHADOW_STACK_PTR_STATE) struct __cfi_status { __u64 cfi_state; diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 5957effab57c..b2df7f72241a 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -160,6 +160,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, * clear shadow stack state on exec. * libc will set it later via prctl. */ + set_shstk_lock(current, false); set_shstk_status(current, false); set_shstk_base(current, 0, 0); set_active_shstk(current, 0); @@ -167,6 +168,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, * disable indirect branch tracking on exec. * libc will enable it later via prctl. */ + set_indir_lp_lock(current, false); set_indir_lp_status(current, false); #ifdef CONFIG_64BIT diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index e592bd6b7665..93de2e7a3074 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -303,18 +303,18 @@ static int riscv_cfi_get(struct task_struct *target, regs = task_pt_regs(target); if (is_indir_lp_enabled(target)) { - user_cfi.cfi_status.cfi_state |= PTRACE_CFI_LP_EN_STATE; + user_cfi.cfi_status.cfi_state |= PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE; user_cfi.cfi_status.cfi_state |= is_indir_lp_locked(target) ? - PTRACE_CFI_LP_LOCK_STATE : 0; + PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE : 0; user_cfi.cfi_status.cfi_state |= (regs->status & SR_ELP) ? - PTRACE_CFI_ELP_STATE : 0; + PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE : 0; } if (is_shstk_enabled(target)) { - user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SS_EN_STATE | - PTRACE_CFI_SS_PTR_STATE); + user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SHADOW_STACK_EN_STATE | + PTRACE_CFI_SHADOW_STACK_PTR_STATE); user_cfi.cfi_status.cfi_state |= is_shstk_locked(target) ? - PTRACE_CFI_SS_LOCK_STATE : 0; + PTRACE_CFI_SHADOW_STACK_LOCK_STATE : 0; user_cfi.shstk_ptr = get_active_shstk(target); } @@ -349,15 +349,15 @@ static int riscv_cfi_set(struct task_struct *target, * rsvd field should be set to zero so that if those fields are needed in future */ if ((user_cfi.cfi_status.cfi_state & - (PTRACE_CFI_LP_EN_STATE | PTRACE_CFI_LP_LOCK_STATE | - PTRACE_CFI_SS_EN_STATE | PTRACE_CFI_SS_LOCK_STATE)) || - (user_cfi.cfi_status.cfi_state & PRACE_CFI_STATE_INVALID_MASK)) + (PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE | + PTRACE_CFI_SHADOW_STACK_EN_STATE | PTRACE_CFI_SHADOW_STACK_LOCK_STATE)) || + (user_cfi.cfi_status.cfi_state & PTRACE_CFI_STATE_INVALID_MASK)) return -EINVAL; /* If lpad is enabled on target and ptrace requests to set / clear elp, do that */ if (is_indir_lp_enabled(target)) { if (user_cfi.cfi_status.cfi_state & - PTRACE_CFI_ELP_STATE) /* set elp state */ + PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE) /* set elp state */ regs->status |= SR_ELP; else regs->status &= ~SR_ELP; /* clear elp state */ @@ -365,7 +365,7 @@ static int riscv_cfi_set(struct task_struct *target, /* If shadow stack enabled on target, set new shadow stack pointer */ if (is_shstk_enabled(target) && - (user_cfi.cfi_status.cfi_state & PTRACE_CFI_SS_PTR_STATE)) + (user_cfi.cfi_status.cfi_state & PTRACE_CFI_SHADOW_STACK_PTR_STATE)) set_active_shstk(target, user_cfi.shstk_ptr); return 0; diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c index 1adba746f164..2c535737511d 100644 --- a/arch/riscv/kernel/usercfi.c +++ b/arch/riscv/kernel/usercfi.c @@ -74,9 +74,9 @@ void set_shstk_status(struct task_struct *task, bool enable) csr_write(CSR_ENVCFG, task->thread.envcfg); } -void set_shstk_lock(struct task_struct *task) +void set_shstk_lock(struct task_struct *task, bool lock) { - task->thread_info.user_cfi_state.ubcfi_locked = 1; + task->thread_info.user_cfi_state.ubcfi_locked = lock; } bool is_indir_lp_enabled(struct task_struct *task) @@ -104,9 +104,9 @@ void set_indir_lp_status(struct task_struct *task, bool enable) csr_write(CSR_ENVCFG, task->thread.envcfg); } -void set_indir_lp_lock(struct task_struct *task) +void set_indir_lp_lock(struct task_struct *task, bool lock) { - task->thread_info.user_cfi_state.ufcfi_locked = 1; + task->thread_info.user_cfi_state.ufcfi_locked = lock; } /* * If size is 0, then to be compatible with regular stack we want it to be as big as @@ -452,28 +452,27 @@ int arch_lock_shadow_stack_status(struct task_struct *task, !is_shstk_enabled(task) || arg != 0) return -EINVAL; - set_shstk_lock(task); + set_shstk_lock(task, true); return 0; } -int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) +int arch_prctl_get_branch_landing_pad_state(struct task_struct *t, + unsigned long __user *state) { unsigned long fcfi_status = 0; if (!is_user_lpad_enabled()) return -EINVAL; - /* indirect branch tracking is enabled on the task or not */ - fcfi_status |= (is_indir_lp_enabled(t) ? PR_INDIR_BR_LP_ENABLE : 0); + fcfi_status = (is_indir_lp_enabled(t) ? PR_CFI_ENABLE : PR_CFI_DISABLE); + fcfi_status |= (is_indir_lp_locked(t) ? PR_CFI_LOCK : 0); - return copy_to_user(status, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0; + return copy_to_user(state, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0; } -int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status) +int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state) { - bool enable_indir_lp = false; - if (!is_user_lpad_enabled()) return -EINVAL; @@ -481,28 +480,28 @@ int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status) if (is_indir_lp_locked(t)) return -EINVAL; - /* Reject unknown flags */ - if (status & ~PR_INDIR_BR_LP_ENABLE) + if (!(state & (PR_CFI_ENABLE | PR_CFI_DISABLE))) + return -EINVAL; + + if (state & PR_CFI_ENABLE && state & PR_CFI_DISABLE) return -EINVAL; - enable_indir_lp = (status & PR_INDIR_BR_LP_ENABLE); - set_indir_lp_status(t, enable_indir_lp); + set_indir_lp_status(t, !!(state & PR_CFI_ENABLE)); return 0; } -int arch_lock_indir_br_lp_status(struct task_struct *task, - unsigned long arg) +int arch_prctl_lock_branch_landing_pad_state(struct task_struct *task) { /* * If indirect branch tracking is not supported or not enabled on task, * nothing to lock here */ if (!is_user_lpad_enabled() || - !is_indir_lp_enabled(task) || arg != 0) + !is_indir_lp_enabled(task)) return -EINVAL; - set_indir_lp_lock(task); + set_indir_lp_lock(task, true); return 0; } |
