summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/riscv/include/asm/usercfi.h8
-rw-r--r--arch/riscv/include/uapi/asm/ptrace.h42
-rw-r--r--arch/riscv/kernel/process.c2
-rw-r--r--arch/riscv/kernel/ptrace.c22
-rw-r--r--arch/riscv/kernel/usercfi.c39
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;
}