linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/6] Add dynamic DEXCR support
@ 2023-10-09  5:54 Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

(This RFC is mainly to get feedback on the user interface. Tests and
documentation will be added to the non-rfc followups. This builds but
is otherwise untested.)

In the "Add static DEXCR support" series[1] the kernel was made to
initialise the DEXCR to a static value on all CPUs when they online.

This series allows the DEXCR value to be changed at runtime with a
per-thread granularity. It provides a prctl interface to set and query
this configuration. It also provides a system wide sysctl override for
the SBHE aspect, which specifically has effects that can bleed over to
other CPUs (temporarily after changing it) and certain tracing tools
may require it be set globally across all threads.

Some notes on the patches/changes from the original RFC:

1. We don't need all the aspects to use feature bits, but the
   aspect information is in the device tree and this is the
   simplest mechanism to access it. Adding some kind of callback
   support to the feature detector would also work.

   The dexcr_supported variable introduced in patch 4 is a half-hearted
   example of how the callbacks could just update that variable, and
   no more CPU features would be necessary.

2. The thread used to track 'default' as a separate state (way back in
   the original RFC before the split into static/dynamic). This RFC
   simplifies it away, as it is only useful if there is a system wide
   default that can be changed. The current system wide default is
   decided at compile time, so we just initialise the thread config
   to that.

   If the 'default' state were added in future though, would that be
   a userspace ABI concern? I guess it could just return a 'default'
   flag as well as the current 'on' and 'off' flags to indicate what
   the default is.

3. The prctl controls are reduced to what I expect to be most useful.
   Default state is removed as above, and so is 'force' (where the aspect
   would no longer be configurable). 'inherit' remains as a way to control
   the DEXCR of child process trees that may not be aware of it.

4. The prctl set interface is privileged. The concern is a non-privileged
   process disabling NPHIE (HASHCHK enabler) and then invoking a setuid
   binary which doesn't set NPHIE itself. It seems that kind of 
   information about the exec target is not available in arch specific
   code.

5. A lot of the synchonization of the sysctl interface is removed.
   Apparently the kernfs system that manages these files enforces
   exclusive access to a given sysctl file. Additionally, the 
   proc_dointvec_minmax() function was made to store the result with 
   WRITE_ONCE(), so we can assume a regular atomic store of an aligned
   word.

6. The ROP protection enforcement is refactored a bit. The idea is to
   allow baking into the kernel at compile time that NPHIE cannot be
   changed by a thread. Seems to allow making the system more secure on
   paper, not sure how useful it is in practice.

7. The prctl interface tries to stay separate from the DEXCR structure.
   This makes it a little contorted (having to convert the prctl value to
   an aspect), but I think makes the interface more robust against future
   changes to the DEXCR. E.g., if all 32 aspect bits were exhausted and a
   second DEXCR added, the current interface could still handle that.


[1]: https://patchwork.ozlabs.org/project/linuxppc-dev/cover/20230616034846.311705-1-bgray@linux.ibm.com/


Benjamin Gray (6):
  powerpc/dexcr: Make all aspects CPU features
  powerpc/dexcr: Add thread specific DEXCR configuration
  prctl: Define PowerPC DEXCR interface
  powerpc/dexcr: Add prctl implementation
  powerpc/dexcr: Add sysctl entry for SBHE system override
  powerpc/dexcr: Add enforced userspace ROP protection config

 arch/powerpc/Kconfig                 |   5 +
 arch/powerpc/include/asm/cputable.h  |   6 +-
 arch/powerpc/include/asm/processor.h |  22 +++
 arch/powerpc/kernel/Makefile         |   1 +
 arch/powerpc/kernel/dexcr.c          | 218 +++++++++++++++++++++++++++
 arch/powerpc/kernel/process.c        |  24 +++
 arch/powerpc/kernel/prom.c           |   3 +
 include/uapi/linux/prctl.h           |  13 ++
 kernel/sys.c                         |  16 ++
 9 files changed, 307 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/kernel/dexcr.c

-- 
2.41.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration Benjamin Gray
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

The CPU_FEATURE_* mechanism is the only way right now to get
configuration from the "ibm,pa-features" devicetree node. Add a
CPU_FEATURE_* entry for each other DEXCR aspect that will be
exposed to userspace.

The NPHIE feature value is changed for consistency; the actual value is
never accessed or exposed to userspace, so there is no breakage.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/include/asm/cputable.h | 6 +++++-
 arch/powerpc/kernel/prom.c          | 3 +++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 8765d5158324..bd087d0cb5fa 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -192,7 +192,10 @@ static inline void cpu_feature_keys_init(void) { }
 #define CPU_FTR_P9_RADIX_PREFETCH_BUG	LONG_ASM_CONST(0x0002000000000000)
 #define CPU_FTR_ARCH_31			LONG_ASM_CONST(0x0004000000000000)
 #define CPU_FTR_DAWR1			LONG_ASM_CONST(0x0008000000000000)
-#define CPU_FTR_DEXCR_NPHIE		LONG_ASM_CONST(0x0010000000000000)
+#define CPU_FTR_DEXCR_SBHE		LONG_ASM_CONST(0x0010000000000000)
+#define CPU_FTR_DEXCR_IBRTPD		LONG_ASM_CONST(0x0020000000000000)
+#define CPU_FTR_DEXCR_SRAPD		LONG_ASM_CONST(0x0040000000000000)
+#define CPU_FTR_DEXCR_NPHIE		LONG_ASM_CONST(0x0080000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -453,6 +456,7 @@ static inline void cpu_feature_keys_init(void) { }
 	    CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
 	    CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \
 	    CPU_FTR_DAWR | CPU_FTR_DAWR1 | \
+	    CPU_FTR_DEXCR_SBHE | CPU_FTR_DEXCR_IBRTPD | CPU_FTR_DEXCR_SRAPD | \
 	    CPU_FTR_DEXCR_NPHIE)
 #define CPU_FTRS_CELL	(CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 0b5878c3125b..ea081a5d2023 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -182,6 +182,9 @@ static struct ibm_feature ibm_pa_features[] __initdata = {
 	  .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP },
 
 	{ .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 },
+	{ .pabyte = 68, .pabit = 0, .cpu_features = CPU_FTR_DEXCR_SBHE },
+	{ .pabyte = 68, .pabit = 3, .cpu_features = CPU_FTR_DEXCR_IBRTPD },
+	{ .pabyte = 68, .pabit = 4, .cpu_features = CPU_FTR_DEXCR_SRAPD },
 	{ .pabyte = 68, .pabit = 5, .cpu_features = CPU_FTR_DEXCR_NPHIE },
 };
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface Benjamin Gray
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

Add capability to track a DEXCR value per thread.

Nothing actually changes these values yet, but they are correctly
tracked, propagated, and used to set the hardware register.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/include/asm/processor.h | 12 ++++++++++++
 arch/powerpc/kernel/process.c        | 24 ++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index b2c51d337e60..28a72023f9bd 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -260,6 +260,9 @@ struct thread_struct {
 	unsigned long   sier2;
 	unsigned long   sier3;
 	unsigned long	hashkeyr;
+	unsigned int	dexcr;		/* Temporary value saved during thread switch */
+	unsigned int	dexcr_enabled;	/* Bitmask of aspects enabled by this thread */
+	unsigned int	dexcr_inherit;	/* Bitmask of aspects to inherit across exec */
 
 #endif
 };
@@ -448,6 +451,15 @@ int exit_vmx_usercopy(void);
 int enter_vmx_ops(void);
 void *exit_vmx_ops(void *dest);
 
+static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	return thread->dexcr_enabled;
+#else
+	return 0;
+#endif
+}
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b68898ac07e1..c05d58b7c6b3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1185,6 +1185,9 @@ static inline void save_sprs(struct thread_struct *t)
 
 	if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
 		t->hashkeyr = mfspr(SPRN_HASHKEYR);
+
+	if (cpu_has_feature(CPU_FTR_ARCH_31))
+		t->dexcr = mfspr(SPRN_DEXCR);
 #endif
 }
 
@@ -1267,6 +1270,10 @@ static inline void restore_sprs(struct thread_struct *old_thread,
 	if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) &&
 	    old_thread->hashkeyr != new_thread->hashkeyr)
 		mtspr(SPRN_HASHKEYR, new_thread->hashkeyr);
+
+	if (cpu_has_feature(CPU_FTR_ARCH_31) &&
+	    old_thread->dexcr != get_thread_dexcr(new_thread))
+		mtspr(SPRN_DEXCR, get_thread_dexcr(new_thread));
 #endif
 
 }
@@ -1634,6 +1641,11 @@ void arch_setup_new_exec(void)
 	current->thread.regs->amr  = default_amr;
 	current->thread.regs->iamr  = default_iamr;
 #endif
+
+#ifdef CONFIG_PPC_BOOK3S_64
+	current->thread.dexcr_enabled &= current->thread.dexcr_inherit;
+	current->thread.dexcr_enabled |= ~current->thread.dexcr_inherit & DEXCR_INIT; 
+#endif
 }
 
 #ifdef CONFIG_PPC64
@@ -1878,6 +1890,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
 #ifdef CONFIG_PPC_BOOK3S_64
 	if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
 		p->thread.hashkeyr = current->thread.hashkeyr;
+
+	if (cpu_has_feature(CPU_FTR_ARCH_31)) {
+		p->thread.dexcr_enabled = current->thread.dexcr_enabled;
+		p->thread.dexcr_inherit = current->thread.dexcr_inherit;
+	}
 #endif
 	return 0;
 }
@@ -2000,6 +2017,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 		current->thread.hashkeyr = get_random_long();
 		mtspr(SPRN_HASHKEYR, current->thread.hashkeyr);
 	}
+
+	if (cpu_has_feature(CPU_FTR_ARCH_31)) {
+		current->thread.dexcr = 0;
+		current->thread.dexcr_enabled = DEXCR_INIT;
+		current->thread.dexcr_inherit = 0;
+		mtspr(SPRN_DEXCR, get_thread_dexcr(&current->thread));
+	}
 #endif /* CONFIG_PPC_BOOK3S_64 */
 }
 EXPORT_SYMBOL(start_thread);
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation Benjamin Gray
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

Adds the definitions and generic handler for prctl control of the
PowerPC Dynamic Execution Control Register (DEXCR).

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 include/uapi/linux/prctl.h | 13 +++++++++++++
 kernel/sys.c               | 16 ++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 3c36aeade991..85d66ad134b1 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -305,4 +305,17 @@ struct prctl_mm_map {
 # define PR_RISCV_V_VSTATE_CTRL_NEXT_MASK	0xc
 # define PR_RISCV_V_VSTATE_CTRL_MASK		0x1f
 
+/* PowerPC Dynamic Execution Control Register (DEXCR) controls */
+#define PR_PPC_GET_DEXCR		71
+#define PR_PPC_SET_DEXCR		72
+/* DEXCR aspect to act on */
+# define PR_PPC_DEXCR_SBHE		0 /* Speculative branch hint enable */
+# define PR_PPC_DEXCR_IBRTPD		1 /* Indirect branch recurrent target prediction disable */
+# define PR_PPC_DEXCR_SRAPD		2 /* Subroutine return address prediction disable */
+# define PR_PPC_DEXCR_NPHIE		3 /* Non-privileged hash instruction enable */
+/* Action to apply / return */
+# define PR_PPC_DEXCR_CTRL_OFF		(1UL << 0)
+# define PR_PPC_DEXCR_CTRL_ON		(1UL << 1)
+# define PR_PPC_DEXCR_CTRL_INHERIT	(1UL << 2)
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 2410e3999ebe..0c1b8e9c3d16 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -146,6 +146,12 @@
 #ifndef RISCV_V_GET_CONTROL
 # define RISCV_V_GET_CONTROL()		(-EINVAL)
 #endif
+#ifndef PPC_GET_DEXCR_ASPECT
+# define PPC_GET_DEXCR_ASPECT(a, b)	(-EINVAL)
+#endif
+#ifndef PPC_SET_DEXCR_ASPECT
+# define PPC_SET_DEXCR_ASPECT(a, b, c)	(-EINVAL)
+#endif
 
 /*
  * this is where the system-wide overflow UID and GID are defined, for
@@ -2686,6 +2692,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 	case PR_GET_MDWE:
 		error = prctl_get_mdwe(arg2, arg3, arg4, arg5);
 		break;
+	case PR_PPC_GET_DEXCR:
+		if (arg3 || arg4 || arg5)
+			return -EINVAL;
+		error = PPC_GET_DEXCR_ASPECT(me, arg2);
+		break;
+	case PR_PPC_SET_DEXCR:
+		if (arg4 || arg5)
+			return -EINVAL;
+		error = PPC_SET_DEXCR_ASPECT(me, arg2, arg3);
+		break;
 	case PR_SET_VMA:
 		error = prctl_set_vma(arg2, arg3, arg4, arg5);
 		break;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
                   ` (2 preceding siblings ...)
  2023-10-09  5:54 ` [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config Benjamin Gray
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

Adds an initial prctl interface implementation. Unprivileged processes
can query the current prctl setting, including whether an aspect is
implemented by the hardware or is permitted to be modified by a setter
prctl. Editable aspects can be changed by a CAP_SYS_ADMIN privileged
process.

The prctl setting represents what the process itself has requested, and
does not account for any overrides. Either the kernel or a hypervisor
may enforce a different setting for an aspect.

Userspace can access a readonly view of the current DEXCR via SPR 812,
and a readonly view of the aspects enforced by the hypervisor via
SPR 455. A bitwise OR of these two SPRs will give the effective
DEXCR aspect state of the process.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/include/asm/processor.h |  10 +++
 arch/powerpc/kernel/Makefile         |   1 +
 arch/powerpc/kernel/dexcr.c          | 128 +++++++++++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 arch/powerpc/kernel/dexcr.c

diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 28a72023f9bd..a9d83621dfad 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -336,6 +336,16 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
 extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
 extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
 
+#ifdef CONFIG_PPC_BOOK3S_64
+
+#define PPC_GET_DEXCR_ASPECT(tsk, asp) get_dexcr_prctl((tsk), (asp))
+#define PPC_SET_DEXCR_ASPECT(tsk, asp, val) set_dexcr_prctl((tsk), (asp), (val))
+
+int get_dexcr_prctl(struct task_struct *tsk, unsigned long asp);
+int set_dexcr_prctl(struct task_struct *tsk, unsigned long asp, unsigned long val);
+
+#endif
+
 extern void load_fp_state(struct thread_fp_state *fp);
 extern void store_fp_state(struct thread_fp_state *fp);
 extern void load_vr_state(struct thread_vr_state *vr);
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2919433be355..24f82b09246c 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
 obj-$(CONFIG_PPC_DAWR)		+= dawr.o
 obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_ppc970.o cpu_setup_pa6t.o
 obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_power.o
+obj-$(CONFIG_PPC_BOOK3S_64)	+= dexcr.o
 obj-$(CONFIG_PPC_BOOK3S_64)	+= mce.o mce_power.o
 obj-$(CONFIG_PPC_BOOK3E_64)	+= exceptions-64e.o idle_64e.o
 obj-$(CONFIG_PPC_BARRIER_NOSPEC) += security.o
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
new file mode 100644
index 000000000000..db663ce7b3ce
--- /dev/null
+++ b/arch/powerpc/kernel/dexcr.c
@@ -0,0 +1,128 @@
+#include <linux/capability.h>
+#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/sched.h>
+
+#include <asm/cpu_has_feature.h>
+#include <asm/cputable.h>
+#include <asm/processor.h>
+#include <asm/reg.h>
+
+/* Allow thread local configuration of these by default */
+#define DEXCR_PRCTL_EDITABLE ( \
+	DEXCR_PR_IBRTPD | \
+	DEXCR_PR_SRAPD | \
+	DEXCR_PR_NPHIE)
+
+static unsigned long dexcr_supported __ro_after_init = 0;
+
+static int __init dexcr_init(void)
+{
+	if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
+		return 0;
+
+	if (early_cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+		dexcr_supported |= DEXCR_PR_SBHE;
+
+	if (early_cpu_has_feature(CPU_FTR_DEXCR_IBRTPD))
+		dexcr_supported |= DEXCR_PR_IBRTPD;
+
+	if (early_cpu_has_feature(CPU_FTR_DEXCR_SRAPD))
+		dexcr_supported |= DEXCR_PR_SRAPD;
+
+	if (early_cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
+		dexcr_supported |= DEXCR_PR_NPHIE;
+
+	return 0;
+}
+early_initcall(dexcr_init);
+
+static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
+{
+	switch (which) {
+	case PR_PPC_DEXCR_SBHE:
+		*aspect = DEXCR_PR_SBHE;
+		break;
+	case PR_PPC_DEXCR_IBRTPD:
+		*aspect = DEXCR_PR_IBRTPD;
+		break;
+	case PR_PPC_DEXCR_SRAPD:
+		*aspect = DEXCR_PR_SRAPD;
+		break;
+	case PR_PPC_DEXCR_NPHIE:
+		*aspect = DEXCR_PR_NPHIE;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+int get_dexcr_prctl(struct task_struct *task, unsigned long which)
+{
+	unsigned int aspect;
+	int ret;
+
+	ret = prctl_to_aspect(which, &aspect);
+	if (ret)
+		return ret;
+	
+	if (!(aspect & dexcr_supported))
+		return -ENODEV;
+
+	if (aspect & task->thread.dexcr_enabled)
+		ret |= PR_PPC_DEXCR_CTRL_ON;
+	else
+		ret |= PR_PPC_DEXCR_CTRL_OFF;
+
+	if (aspect & task->thread.dexcr_inherit)
+		ret |= PR_PPC_DEXCR_CTRL_INHERIT;
+
+	return ret;
+}
+
+int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long ctrl)
+{
+	unsigned int aspect;
+	unsigned long enable;
+	unsigned long disable;
+	unsigned long inherit;
+	int err = 0;
+
+	/* We do not want an unprivileged process being able to set a value that a setuid process may inherit (particularly for NPHIE) */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	err = prctl_to_aspect(which, &aspect);
+	if (err)
+		return err;
+
+	if (!(aspect & dexcr_supported))
+		return -ENODEV;
+
+	enable = ctrl & PR_PPC_DEXCR_CTRL_ON;
+	disable = ctrl & PR_PPC_DEXCR_CTRL_OFF;
+	inherit = ctrl & PR_PPC_DEXCR_CTRL_INHERIT;
+	ctrl &= ~(PR_PPC_DEXCR_CTRL_ON | PR_PPC_DEXCR_CTRL_OFF | PR_PPC_DEXCR_CTRL_INHERIT);
+
+	if (ctrl)
+		return -EINVAL;
+
+	if ((enable && disable) || !(enable || disable))
+		return -EINVAL;
+
+	if (enable)
+		task->thread.dexcr_enabled |= aspect;
+	else
+		task->thread.dexcr_enabled &= ~aspect;
+
+	if (inherit)
+		task->thread.dexcr_inherit |= aspect;
+	else
+		task->thread.dexcr_inherit &= ~aspect;
+
+	mtspr(SPRN_DEXCR, get_thread_dexcr(&current->thread));
+
+	return 0;
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
                   ` (3 preceding siblings ...)
  2023-10-09  5:54 ` [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  2023-10-09  5:54 ` [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config Benjamin Gray
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

The DEXCR Speculative Branch Hint Enable (SBHE) aspect controls whether
the hints provided by BO field of Branch instructions are obeyed during
speculative execution.

SBHE behaviour per ISA 3.1B:

0:	The hints provided by BO field of Branch instructions may be
	ignored during speculative execution

1:	The hints provided by BO field of Branch instructions are obeyed
	during speculative execution

Add a sysctl entry to allow changing this aspect globally in the system
at runtime:

	/proc/sys/kernel/speculative_branch_hint_enable

Three values are supported:

-1:	Disable DEXCR SBHE sysctl override
 0:	Override and set DEXCR[SBHE] aspect to 0
 1:	Override and set DEXCR[SBHE] aspect to 1

Internally, introduces a mechanism to apply arbitrary system wide
overrides on top of the prctl() config.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/include/asm/processor.h |  8 +--
 arch/powerpc/kernel/dexcr.c          | 85 ++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index a9d83621dfad..e7b732efb968 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -461,14 +461,14 @@ int exit_vmx_usercopy(void);
 int enter_vmx_ops(void);
 void *exit_vmx_ops(void *dest);
 
-static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
-{
 #ifdef CONFIG_PPC_BOOK3S_64
-	return thread->dexcr_enabled;
+unsigned long get_thread_dexcr(struct thread_struct const *thread);
 #else
+static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
 	return 0;
-#endif
 }
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
index db663ce7b3ce..e790f76787db 100644
--- a/arch/powerpc/kernel/dexcr.c
+++ b/arch/powerpc/kernel/dexcr.c
@@ -1,7 +1,9 @@
 #include <linux/capability.h>
+#include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/prctl.h>
 #include <linux/sched.h>
+#include <linux/sysctl.h>
 
 #include <asm/cpu_has_feature.h>
 #include <asm/cputable.h>
@@ -16,6 +18,8 @@
 
 static unsigned long dexcr_supported __ro_after_init = 0;
 
+static int spec_branch_hint_enable = -1;
+
 static int __init dexcr_init(void)
 {
 	if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
@@ -37,6 +41,35 @@ static int __init dexcr_init(void)
 }
 early_initcall(dexcr_init);
 
+unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
+	unsigned long dexcr = thread->dexcr_enabled;
+
+	/* 
+	 * spec_branch_hint_enable may be written to concurrently via sysctl.
+	 * The sysctl handler is careful to use WRITE_ONCE, so we avoid
+	 * tearing/different values with READ_ONCE 
+	 */
+	switch (READ_ONCE(spec_branch_hint_enable)) {
+	case 0:
+		dexcr &= ~DEXCR_PR_SBHE;
+		break;
+	case 1:
+		dexcr |= DEXCR_PR_SBHE;
+		break;
+	}
+
+	return dexcr;
+}
+
+static void update_dexcr_on_cpu(void *_info)
+{
+	/* ensure the spec_branch_hint_enable write propagated to this CPU */
+	smp_mb();
+
+	mtspr(SPRN_DEXCR, get_thread_dexcr(&current->thread));
+}
+
 static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
 {
 	switch (which) {
@@ -126,3 +159,55 @@ int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long
 
 	return 0;
 }
+
+#ifdef CONFIG_SYSCTL
+
+static const int min_sysctl_val = -1;
+
+static int sysctl_dexcr_sbhe_handler(struct ctl_table *table, int write,
+				     void *buf, size_t *lenp, loff_t *ppos)
+{
+	int err = 0;
+	int prev;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+		return -ENODEV;
+
+	prev = READ_ONCE(spec_branch_hint_enable);
+	
+	err = proc_dointvec_minmax(table, write, buf, lenp, ppos);
+	if (err)
+		return err;
+
+	if (spec_branch_hint_enable != prev && write)
+		on_each_cpu(update_dexcr_on_cpu, NULL, 1);
+
+	return 0;
+}
+
+static struct ctl_table dexcr_sbhe_ctl_table[] = {
+	{
+		.procname	= "speculative_branch_hint_enable",
+		.data		= &spec_branch_hint_enable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= sysctl_dexcr_sbhe_handler,
+		.extra1		= (void *)&min_sysctl_val,
+		.extra2		= SYSCTL_ONE,
+	}
+};
+
+static int __init register_dexcr_aspects_sysctl(void)
+{
+	if (!early_cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+		return -ENODEV;
+
+	register_sysctl("kernel", dexcr_sbhe_ctl_table);
+	return 0;
+}
+device_initcall(register_dexcr_aspects_sysctl);
+
+#endif /* CONFIG_SYSCTL */
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config
  2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
                   ` (4 preceding siblings ...)
  2023-10-09  5:54 ` [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override Benjamin Gray
@ 2023-10-09  5:54 ` Benjamin Gray
  5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09  5:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray

The DEXCR Non-Privileged Hash Instruction Enable (NPHIE) aspect controls
whether the hashst and hashchk instructions are treated as no-ops by the
CPU.

NPHIE behaviour per ISA 3.1B:

0:	hashst and hashchk instructions are executed as no-ops
	(even when allowed by PCR)

1:	hashst and hashchk instructions are executed normally
	(if allowed by PCR)

Currently this aspect may be set per-process by prctl() or enforced
globally by the hypervisor.

Add a kernel config option PPC_USER_ENFORCE_ROP_PROTECT to enforce
DEXCR[NPHIE] globally regardless of prctl() or hypervisor. If set, don't
report NPHIE as editable via prctl(), as the prctl() value can never
take effect.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/Kconfig        | 5 +++++
 arch/powerpc/kernel/dexcr.c | 7 ++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3aaadfd2c8eb..4851cb463dc0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -473,6 +473,11 @@ config PGTABLE_LEVELS
 	default 2 if !PPC64
 	default 4
 
+config PPC_USER_ENFORCE_ROP_PROTECT
+	bool
+	depends on PPC_BOOK3S_64
+	default y
+
 source "arch/powerpc/sysdev/Kconfig"
 source "arch/powerpc/platforms/Kconfig"
 
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
index e790f76787db..01d8fa28ca17 100644
--- a/arch/powerpc/kernel/dexcr.c
+++ b/arch/powerpc/kernel/dexcr.c
@@ -1,6 +1,8 @@
+#include <linux/cache.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
 #include <linux/init.h>
+#include <linux/kconfig.h>
 #include <linux/prctl.h>
 #include <linux/sched.h>
 #include <linux/sysctl.h>
@@ -14,7 +16,7 @@
 #define DEXCR_PRCTL_EDITABLE ( \
 	DEXCR_PR_IBRTPD | \
 	DEXCR_PR_SRAPD | \
-	DEXCR_PR_NPHIE)
+	(!IS_ENABLED(CONFIG_PPC_USER_ENFORCE_ROP_PROTECT) ? DEXCR_PR_NPHIE : 0))
 
 static unsigned long dexcr_supported __ro_after_init = 0;
 
@@ -45,6 +47,9 @@ unsigned long get_thread_dexcr(struct thread_struct const *thread)
 {
 	unsigned long dexcr = thread->dexcr_enabled;
 
+	if (IS_ENABLED(CONFIG_PPC_USER_ENFORCE_ROP_PROTECT))
+		dexcr |= DEXCR_PR_NPHIE;
+
 	/* 
 	 * spec_branch_hint_enable may be written to concurrently via sysctl.
 	 * The sysctl handler is careful to use WRITE_ONCE, so we avoid
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-10-09  6:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-09  5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override Benjamin Gray
2023-10-09  5:54 ` [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config Benjamin Gray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).