On Wed, Apr 03, 2024 at 04:35:05PM -0700, Deepak Gupta wrote:
Three architectures (x86, aarch64, riscv) have support for indirect branch tracking feature in a very similar fashion. On a very high level, indirect branch tracking is a CPU feature where CPU tracks branches which uses memory operand to perform control transfer in program. As part of this tracking on indirect branches, CPU goes in a state where it expects a landing pad instr on target and if not found then CPU raises some fault (architecture dependent)
x86 landing pad instr - `ENDBRANCH` aarch64 landing pad instr - `BTI` riscv landing instr - `lpad`
Given that three major arches have support for indirect branch tracking, This patch makes `prctl` for indirect branch tracking arch agnostic.
To allow userspace to enable this feature for itself, following prtcls are defined:
- PR_GET_INDIR_BR_LP_STATUS: Gets current configured status for indirect branch tracking.
- PR_SET_INDIR_BR_LP_STATUS: Sets a configuration for indirect branch tracking. Following status options are allowed - PR_INDIR_BR_LP_ENABLE: Enables indirect branch tracking on user thread. - PR_INDIR_BR_LP_DISABLE; Disables indirect branch tracking on user thread.
- PR_LOCK_INDIR_BR_LP_STATUS: Locks configured status for indirect branch tracking for user thread.
Signed-off-by: Deepak Gupta debug@rivosinc.com
include/uapi/linux/prctl.h | 27 +++++++++++++++++++++++++++ kernel/sys.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 3c66ed8f46d8..b7a8212a068e 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -328,4 +328,31 @@ struct prctl_mm_map { */ #define PR_LOCK_SHADOW_STACK_STATUS 73 +/*
- Get the current indirect branch tracking configuration for the current
- thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS.
- */
+#define PR_GET_INDIR_BR_LP_STATUS 74
+/*
- Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will
- enable cpu feature for user thread, to track all indirect branches and ensure
- they land on arch defined landing pad instruction.
- x86 - If enabled, an indirect branch must land on `ENDBRANCH` instruction.
- arch64 - If enabled, an indirect branch must land on `BTI` instruction.
- riscv - If enabled, an indirect branch must land on `lpad` instruction.
- PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect
- branches will no more be tracked by cpu to land on arch defined landing pad
- instruction.
- */
+#define PR_SET_INDIR_BR_LP_STATUS 75 +# define PR_INDIR_BR_LP_ENABLE (1UL << 0)
+/*
- Prevent further changes to the specified indirect branch tracking
- configuration. All bits may be locked via this call, including
- undefined bits.
- */
+#define PR_LOCK_INDIR_BR_LP_STATUS 76
#endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 242e9f147791..c770060c3f06 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2330,6 +2330,21 @@ int __weak arch_lock_shadow_stack_status(struct task_struct *t, unsigned long st return -EINVAL; } +int __weak arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) +{
- return -EINVAL;
+}
+int __weak arch_set_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) +{
- return -EINVAL;
+}
+int __weak arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) +{
- return -EINVAL;
+}
These weak references each cause a warning:
kernel/sys.c:2333:12: warning: no previous prototype for 'arch_get_indir_br_lp_status' [-Wmissing-prototypes] 2333 | int __weak arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/sys.c:2338:12: warning: no previous prototype for 'arch_set_indir_br_lp_status' [-Wmissing-prototypes] 2338 | int __weak arch_set_indir_br_lp_status(struct task_struct *t, unsigned long __user *status) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/sys.c:2343:12: warning: no previous prototype for 'arch_lock_indir_br_lp_status' [-Wmissing-prototypes] 2343 | int __weak arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
Can the definitions be added to include/linux/mm.h alongside the *_shadow_stack_status() definitions?
- Charlie
#define PR_IO_FLUSHER (PF_MEMALLOC_NOIO | PF_LOCAL_THROTTLE) #ifdef CONFIG_ANON_VMA_NAME @@ -2787,6 +2802,21 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, return -EINVAL; error = arch_lock_shadow_stack_status(me, arg2); break;
- case PR_GET_INDIR_BR_LP_STATUS:
if (arg3 || arg4 || arg5)
return -EINVAL;
error = arch_get_indir_br_lp_status(me, (unsigned long __user *) arg2);
break;
- case PR_SET_INDIR_BR_LP_STATUS:
if (arg3 || arg4 || arg5)
return -EINVAL;
error = arch_set_indir_br_lp_status(me, (unsigned long __user *) arg2);
break;
- case PR_LOCK_INDIR_BR_LP_STATUS:
if (arg3 || arg4 || arg5)
return -EINVAL;
error = arch_lock_indir_br_lp_status(me, (unsigned long __user *) arg2);
default: error = -EINVAL; break;break;
-- 2.43.2