Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 338d4f49 authored by James Morse's avatar James Morse Committed by Will Deacon
Browse files

arm64: kernel: Add support for Privileged Access Never



'Privileged Access Never' is a new arm8.1 feature which prevents
privileged code from accessing any virtual address where read or write
access is also permitted at EL0.

This patch enables the PAN feature on all CPUs, and modifies {get,put}_user
helpers temporarily to permit access.

This will catch kernel bugs where user memory is accessed directly.
'Unprivileged loads and stores' using ldtrb et al are unaffected by PAN.

Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
[will: use ALTERNATIVE in asm and tidy up pan_enable check]
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 9ded63aa
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -596,6 +596,20 @@ config FORCE_MAX_ZONEORDER
	default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
	default "11"

config ARM64_PAN
	bool "Enable support for Privileged Access Never (PAN)"
	default y
	help
	 Privileged Access Never (PAN; part of the ARMv8.1 Extensions)
	 prevents the kernel or hypervisor from accessing user-space (EL0)
	 memory directly.

	 Choosing this option will cause any unprotected (not using
	 copy_to_user et al) memory access to fail with a permission fault.

	 The feature is detected at runtime, and will remain as a 'nop'
	 instruction if the cpu does not implement the feature.

menuconfig ARMV8_DEPRECATED
	bool "Emulate deprecated/obsolete ARMv8 instructions"
	depends on COMPAT
+2 −1
Original line number Diff line number Diff line
@@ -25,8 +25,9 @@
#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE	1
#define ARM64_WORKAROUND_845719			2
#define ARM64_HAS_SYSREG_GIC_CPUIF		3
#define ARM64_HAS_PAN				4

#define ARM64_NCAPS				4
#define ARM64_NCAPS				5

#ifndef __ASSEMBLY__

+8 −0
Original line number Diff line number Diff line
@@ -20,10 +20,16 @@

#include <linux/futex.h>
#include <linux/uaccess.h>

#include <asm/alternative.h>
#include <asm/cpufeature.h>
#include <asm/errno.h>
#include <asm/sysreg.h>

#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg)		\
	asm volatile(							\
	ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,		\
		    CONFIG_ARM64_PAN)					\
"1:	ldxr	%w1, %2\n"						\
	insn "\n"							\
"2:	stlxr	%w3, %w0, %2\n"						\
@@ -39,6 +45,8 @@
"	.align	3\n"							\
"	.quad	1b, 4b, 2b, 4b\n"					\
"	.popsection\n"							\
	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,		\
		    CONFIG_ARM64_PAN)					\
	: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp)	\
	: "r" (oparg), "Ir" (-EFAULT)					\
	: "memory")
+2 −0
Original line number Diff line number Diff line
@@ -186,4 +186,6 @@ static inline void spin_lock_prefetch(const void *x)

#endif

void cpu_enable_pan(void);

#endif /* __ASM_PROCESSOR_H */
+8 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#ifndef __ASM_SYSREG_H
#define __ASM_SYSREG_H

#include <asm/opcodes.h>

#define SCTLR_EL1_CP15BEN	(0x1 << 5)
#define SCTLR_EL1_SED		(0x1 << 8)

@@ -36,6 +38,12 @@
#define sys_reg(op0, op1, crn, crm, op2) \
	((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))

#define REG_PSTATE_PAN_IMM                     sys_reg(0, 0, 4, 0, 4)
#define SCTLR_EL1_SPAN                         (1 << 23)

#define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\
				     (!!x)<<8 | 0x1f)

#ifdef __ASSEMBLY__

	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
Loading