From: Zong Li <zong.li@sifive.com>
To: Deepak Gupta <debug@rivosinc.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Andrew Morton <akpm@linux-foundation.org>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Vlastimil Babka <vbabka@suse.cz>,
Lorenzo Stoakes <lorenzo.stoakes@oracle.com>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Conor Dooley <conor@kernel.org>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Arnd Bergmann <arnd@arndb.de>,
Christian Brauner <brauner@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Oleg Nesterov <oleg@redhat.com>,
Eric Biederman <ebiederm@xmission.com>,
Kees Cook <kees@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <shuah@kernel.org>, Jann Horn <jannh@google.com>,
Conor Dooley <conor+dt@kernel.org>,
linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-mm@kvack.org, linux-riscv@lists.infradead.org,
devicetree@vger.kernel.org, linux-arch@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
alistair.francis@wdc.com, richard.henderson@linaro.org,
jim.shu@sifive.com, andybnac@gmail.com, kito.cheng@sifive.com,
charlie@rivosinc.com, atishp@rivosinc.com, evan@rivosinc.com,
cleger@rivosinc.com, alexghiti@rivosinc.com,
samitolvanen@google.com, broonie@kernel.org,
rick.p.edgecombe@intel.com
Subject: Re: [PATCH v11 13/27] prctl: arch-agnostic prctl for indirect branch tracking
Date: Fri, 14 Mar 2025 16:25:59 +0800 [thread overview]
Message-ID: <CANXhq0r1dd2jCtCbinD4iy9rx+oQ+VDMWjATf1GqxEmuvFzyWw@mail.gmail.com> (raw)
In-Reply-To: <20250310-v5_user_cfi_series-v11-13-86b36cbfb910@rivosinc.com>
On Mon, Mar 10, 2025 at 11:42 PM Deepak Gupta <debug@rivosinc.com> 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>
> Reviewed-by: Mark Brown <broonie@kernel.org>
> ---
> arch/riscv/include/asm/usercfi.h | 16 ++++++++-
> arch/riscv/kernel/entry.S | 2 +-
> arch/riscv/kernel/process.c | 5 +++
> arch/riscv/kernel/usercfi.c | 76 ++++++++++++++++++++++++++++++++++++++++
> include/linux/cpu.h | 4 +++
> include/uapi/linux/prctl.h | 27 ++++++++++++++
> kernel/sys.c | 30 ++++++++++++++++
> 7 files changed, 158 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h
> index c4dcd256f19a..a8cec7c14d1d 100644
> --- a/arch/riscv/include/asm/usercfi.h
> +++ b/arch/riscv/include/asm/usercfi.h
> @@ -16,7 +16,9 @@ struct kernel_clone_args;
> struct cfi_status {
> unsigned long ubcfi_en : 1; /* Enable for backward cfi. */
> unsigned long ubcfi_locked : 1;
> - unsigned long rsvd : ((sizeof(unsigned long) * 8) - 2);
> + unsigned long ufcfi_en : 1; /* Enable for forward cfi. Note that ELP goes in sstatus */
> + unsigned long ufcfi_locked : 1;
> + unsigned long rsvd : ((sizeof(unsigned long) * 8) - 4);
> unsigned long user_shdw_stk; /* Current user shadow stack pointer */
> unsigned long shdw_stk_base; /* Base address of shadow stack */
> unsigned long shdw_stk_size; /* size of shadow stack */
> @@ -33,6 +35,10 @@ 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_status(struct task_struct *task, bool enable);
> +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);
>
> #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE)
>
> @@ -58,6 +64,14 @@ void set_shstk_status(struct task_struct *task, bool enable);
>
> #define set_shstk_status(task, enable)
>
> +#define is_indir_lp_enabled(task) false
> +
> +#define is_indir_lp_locked(task) false
> +
> +#define set_indir_lp_status(task, enable)
> +
> +#define set_indir_lp_lock(task)
> +
> #endif /* CONFIG_RISCV_USER_CFI */
>
> #endif /* __ASSEMBLY__ */
> diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
> index 68c99124ea55..00494b54ff4a 100644
> --- a/arch/riscv/kernel/entry.S
> +++ b/arch/riscv/kernel/entry.S
> @@ -143,7 +143,7 @@ SYM_CODE_START(handle_exception)
> * Disable the FPU/Vector to detect illegal usage of floating point
> * or vector in kernel space.
> */
> - li t0, SR_SUM | SR_FS_VS
> + li t0, SR_SUM | SR_FS_VS | SR_ELP
>
> REG_L s0, TASK_TI_USER_SP(tp)
> csrrc s1, CSR_STATUS, t0
> diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
> index cd11667593fe..4587201dd81d 100644
> --- a/arch/riscv/kernel/process.c
> +++ b/arch/riscv/kernel/process.c
> @@ -160,6 +160,11 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
> set_shstk_status(current, false);
> set_shstk_base(current, 0, 0);
> set_active_shstk(current, 0);
> + /*
> + * disable indirect branch tracking on exec.
> + * libc will enable it later via prctl.
> + */
> + set_indir_lp_status(current, false);
In set_indir_lp_status and set_shstk_status, the $senvcfg.LPE and
$senvcfg.SSE fields are set. However, if the CPU does not support this
CSR, writing to it will trigger an illegal instruction exception.
Should we add sanity checks to handle this situation? Thanks
>
> #ifdef CONFIG_64BIT
> regs->status &= ~SR_UXL;
> diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
> index 37d6fb8144e7..3a66f149a4ef 100644
> --- a/arch/riscv/kernel/usercfi.c
> +++ b/arch/riscv/kernel/usercfi.c
> @@ -69,6 +69,32 @@ void set_shstk_lock(struct task_struct *task)
> task->thread_info.user_cfi_state.ubcfi_locked = 1;
> }
>
> +bool is_indir_lp_enabled(struct task_struct *task)
> +{
> + return task->thread_info.user_cfi_state.ufcfi_en ? true : false;
> +}
> +
> +bool is_indir_lp_locked(struct task_struct *task)
> +{
> + return task->thread_info.user_cfi_state.ufcfi_locked ? true : false;
> +}
> +
> +void set_indir_lp_status(struct task_struct *task, bool enable)
> +{
> + task->thread_info.user_cfi_state.ufcfi_en = enable ? 1 : 0;
> +
> + if (enable)
> + task->thread.envcfg |= ENVCFG_LPE;
> + else
> + task->thread.envcfg &= ~ENVCFG_LPE;
> +
> + csr_write(CSR_ENVCFG, task->thread.envcfg);
> +}
> +
> +void set_indir_lp_lock(struct task_struct *task)
> +{
> + task->thread_info.user_cfi_state.ufcfi_locked = 1;
> +}
> /*
> * If size is 0, then to be compatible with regular stack we want it to be as big as
> * regular stack. Else PAGE_ALIGN it and return back
> @@ -369,3 +395,53 @@ int arch_lock_shadow_stack_status(struct task_struct *task,
>
> return 0;
> }
> +
> +int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
> +{
> + unsigned long fcfi_status = 0;
> +
> + if (!cpu_supports_indirect_br_lp_instr())
> + 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);
> +
> + return copy_to_user(status, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
> +}
> +
> +int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
> +{
> + bool enable_indir_lp = false;
> +
> + if (!cpu_supports_indirect_br_lp_instr())
> + return -EINVAL;
> +
> + /* indirect branch tracking is locked and further can't be modified by user */
> + if (is_indir_lp_locked(t))
> + return -EINVAL;
> +
> + /* Reject unknown flags */
> + if (status & ~PR_INDIR_BR_LP_ENABLE)
> + return -EINVAL;
> +
> + enable_indir_lp = (status & PR_INDIR_BR_LP_ENABLE) ? true : false;
> + set_indir_lp_status(t, enable_indir_lp);
> +
> + return 0;
> +}
> +
> +int arch_lock_indir_br_lp_status(struct task_struct *task,
> + unsigned long arg)
> +{
> + /*
> + * If indirect branch tracking is not supported or not enabled on task,
> + * nothing to lock here
> + */
> + if (!cpu_supports_indirect_br_lp_instr() ||
> + !is_indir_lp_enabled(task) || arg != 0)
> + return -EINVAL;
> +
> + set_indir_lp_lock(task);
> +
> + return 0;
> +}
> diff --git a/include/linux/cpu.h b/include/linux/cpu.h
> index 6a0a8f1c7c90..fb0c394430c6 100644
> --- a/include/linux/cpu.h
> +++ b/include/linux/cpu.h
> @@ -204,4 +204,8 @@ static inline bool cpu_mitigations_auto_nosmt(void)
> }
> #endif
>
> +int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status);
> +int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status);
> +int arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status);
> +
> #endif /* _LINUX_CPU_H_ */
> diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
> index 5c6080680cb2..6cd90460cbad 100644
> --- a/include/uapi/linux/prctl.h
> +++ b/include/uapi/linux/prctl.h
> @@ -353,4 +353,31 @@ struct prctl_mm_map {
> */
> #define PR_LOCK_SHADOW_STACK_STATUS 76
>
> +/*
> + * 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 77
> +
> +/*
> + * 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 78
> +# 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 79
> +
> #endif /* _LINUX_PRCTL_H */
> diff --git a/kernel/sys.c b/kernel/sys.c
> index cb366ff8703a..f347f3518d0b 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -2336,6 +2336,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 status)
> +{
> + return -EINVAL;
> +}
> +
> +int __weak arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status)
> +{
> + return -EINVAL;
> +}
> +
> #define PR_IO_FLUSHER (PF_MEMALLOC_NOIO | PF_LOCAL_THROTTLE)
>
> #ifdef CONFIG_ANON_VMA_NAME
> @@ -2811,6 +2826,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, arg2);
> + break;
> + case PR_LOCK_INDIR_BR_LP_STATUS:
> + if (arg3 || arg4 || arg5)
> + return -EINVAL;
> + error = arch_lock_indir_br_lp_status(me, arg2);
> + break;
> default:
> trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);
> error = -EINVAL;
>
> --
> 2.34.1
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2025-03-14 8:26 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-10 14:52 [PATCH v11 00/27] riscv control-flow integrity for usermode Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 01/27] mm: VM_SHADOW_STACK definition for riscv Deepak Gupta
2025-03-14 8:27 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 02/27] dt-bindings: riscv: zicfilp and zicfiss in dt-bindings (extensions.yaml) Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 03/27] riscv: zicfiss / zicfilp enumeration Deepak Gupta
2025-03-14 8:10 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 04/27] riscv: zicfiss / zicfilp extension csr and bit definitions Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 05/27] riscv: usercfi state for task and save/restore of CSR_SSP on trap entry/exit Deepak Gupta
2025-03-14 8:28 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 06/27] riscv/mm : ensure PROT_WRITE leads to VM_READ | VM_WRITE Deepak Gupta
2025-03-14 8:28 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 07/27] riscv mm: manufacture shadow stack pte Deepak Gupta
2025-03-14 8:29 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 08/27] riscv mmu: teach pte_mkwrite to manufacture shadow stack PTEs Deepak Gupta
2025-03-14 8:29 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 09/27] riscv mmu: write protect and shadow stack Deepak Gupta
2025-03-14 8:29 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 10/27] riscv/mm: Implement map_shadow_stack() syscall Deepak Gupta
2025-03-14 8:30 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 11/27] riscv/shstk: If needed allocate a new shadow stack on clone Deepak Gupta
2025-03-14 8:30 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 12/27] riscv: Implements arch agnostic shadow stack prctls Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 13/27] prctl: arch-agnostic prctl for indirect branch tracking Deepak Gupta
2025-03-14 8:25 ` Zong Li [this message]
2025-03-14 16:19 ` Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 14/27] riscv/traps: Introduce software check exception Deepak Gupta
2025-03-14 8:31 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 15/27] riscv: signal: abstract header saving for setup_sigcontext Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 16/27] riscv/signal: save and restore of shadow stack for signal Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 17/27] riscv/kernel: update __show_regs to print shadow stack register Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 18/27] riscv/ptrace: riscv cfi status and state via ptrace and in core files Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 19/27] riscv/hwprobe: zicfilp / zicfiss enumeration in hwprobe Deepak Gupta
2025-03-14 8:32 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 20/27] riscv: Add Firmware Feature SBI extensions definitions Deepak Gupta
2025-03-14 8:32 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 21/27] riscv: enable kernel access to shadow stack memory via FWFT sbi call Deepak Gupta
2025-03-14 8:33 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 22/27] riscv: kernel command line option to opt out of user cfi Deepak Gupta
2025-03-10 14:52 ` [PATCH v11 23/27] arch/riscv: compile vdso with landing pad Deepak Gupta
2025-03-14 7:37 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 24/27] riscv: create a config for shadow stack and landing pad instr support Deepak Gupta
2025-03-14 8:33 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 25/27] riscv: Documentation for landing pad / indirect branch tracking Deepak Gupta
2025-03-14 8:34 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 26/27] riscv: Documentation for shadow stack on riscv Deepak Gupta
2025-03-14 8:34 ` Zong Li
2025-03-10 14:52 ` [PATCH v11 27/27] kselftest/riscv: kselftest for user mode cfi Deepak Gupta
2025-03-14 8:07 ` Zong Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CANXhq0r1dd2jCtCbinD4iy9rx+oQ+VDMWjATf1GqxEmuvFzyWw@mail.gmail.com \
--to=zong.li@sifive.com \
--cc=Liam.Howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=alexghiti@rivosinc.com \
--cc=alistair.francis@wdc.com \
--cc=andybnac@gmail.com \
--cc=aou@eecs.berkeley.edu \
--cc=arnd@arndb.de \
--cc=atishp@rivosinc.com \
--cc=bp@alien8.de \
--cc=brauner@kernel.org \
--cc=broonie@kernel.org \
--cc=charlie@rivosinc.com \
--cc=cleger@rivosinc.com \
--cc=conor+dt@kernel.org \
--cc=conor@kernel.org \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=debug@rivosinc.com \
--cc=devicetree@vger.kernel.org \
--cc=ebiederm@xmission.com \
--cc=evan@rivosinc.com \
--cc=hpa@zytor.com \
--cc=jannh@google.com \
--cc=jim.shu@sifive.com \
--cc=kees@kernel.org \
--cc=kito.cheng@sifive.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-riscv@lists.infradead.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=peterz@infradead.org \
--cc=richard.henderson@linaro.org \
--cc=rick.p.edgecombe@intel.com \
--cc=robh@kernel.org \
--cc=samitolvanen@google.com \
--cc=shuah@kernel.org \
--cc=tglx@linutronix.de \
--cc=vbabka@suse.cz \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox