Message ID | 20240403234054.2020347-18-debug@rivosinc.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | riscv control-flow integrity for usermode | expand |
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); > + break; > default: > error = -EINVAL; > break; > -- > 2.43.2 >
On Fri, May 10, 2024 at 04:29:19PM -0700, Charlie Jenkins wrote: >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? Noted. Will work on a fix for this. > >- 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); >> + break; >> default: >> error = -EINVAL; >> break; >> -- >> 2.43.2 >>
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; +} + #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); + break; default: error = -EINVAL; break;
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(+)