Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add support for Privileged Access Never (ARMv8.1-PAN).
details: https://anonhg.NetBSD.org/src/rev/a9ff7dfc3d34
branches: trunk
changeset: 936702:a9ff7dfc3d34
user: maxv <maxv%NetBSD.org@localhost>
date: Sun Aug 02 06:58:16 2020 +0000
description:
Add support for Privileged Access Never (ARMv8.1-PAN).
PAN provides the same functionality as SMAP on x86: it forbids kernel
access to userland pages when PSTATE.PAN=1, and allows such accesses when
PSTATE.PAN=0.
We clear SCTLR_SPAN, to guarantee that PAN=1 each time the kernel is
entered. We catch PAN faults and panic right away without further
processing. In copyin, copyout, etc, we temporarily authorize access to
userland pages.
PAN is a very useful exploit mitigation. Reviewed by ryo@, thanks. Tested
on Qemu. Enabled by default.
diffstat:
sys/arch/aarch64/aarch64/aarch64_machdep.c | 12 ++++++++-
sys/arch/aarch64/aarch64/copyinout.S | 26 ++++++++++++++++++++-
sys/arch/aarch64/aarch64/cpufunc.c | 35 ++++++++++++++++++++++++++++-
sys/arch/aarch64/aarch64/db_interface.c | 10 ++++++-
sys/arch/aarch64/aarch64/fault.c | 20 +++++++++++++++-
sys/arch/aarch64/aarch64/fusu.S | 27 +++++++++++++++++++++-
sys/arch/aarch64/aarch64/locore.S | 12 ++++++++-
sys/arch/aarch64/aarch64/trap.c | 9 ++++++-
sys/arch/aarch64/include/armreg.h | 6 ++++-
sys/arch/aarch64/include/asm.h | 10 ++++++--
sys/arch/aarch64/include/cpufunc.h | 4 ++-
sys/arch/arm/conf/files.arm | 3 +-
sys/arch/evbarm/conf/GENERIC64 | 5 +++-
13 files changed, 156 insertions(+), 23 deletions(-)
diffs (truncated from 501 to 300 lines):
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/aarch64_machdep.c
--- a/sys/arch/aarch64/aarch64/aarch64_machdep.c Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/aarch64_machdep.c Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: aarch64_machdep.c,v 1.45 2020/07/16 11:36:35 skrll Exp $ */
+/* $NetBSD: aarch64_machdep.c,v 1.46 2020/08/02 06:58:16 maxv Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.45 2020/07/16 11:36:35 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.46 2020/08/02 06:58:16 maxv Exp $");
#include "opt_arm_debug.h"
#include "opt_cpuoptions.h"
@@ -480,6 +480,14 @@
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
+ CTLTYPE_INT, "pan",
+ SYSCTL_DESCR("Whether Privileged Access Never is enabled"),
+ NULL, 0,
+ &aarch64_pan_enabled, 0,
+ CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+
+ sysctl_createv(clog, 0, NULL, NULL,
+ CTLFLAG_PERMANENT,
CTLTYPE_INT, "pac",
SYSCTL_DESCR("Whether Pointer Authentication is enabled"),
NULL, 0,
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/copyinout.S
--- a/sys/arch/aarch64/aarch64/copyinout.S Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/copyinout.S Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: copyinout.S,v 1.10 2020/06/30 16:20:00 maxv Exp $ */
+/* $NetBSD: copyinout.S,v 1.11 2020/08/02 06:58:16 maxv Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -33,7 +33,27 @@
#include <aarch64/asm.h>
#include "assym.h"
-RCSID("$NetBSD: copyinout.S,v 1.10 2020/06/30 16:20:00 maxv Exp $");
+RCSID("$NetBSD: copyinout.S,v 1.11 2020/08/02 06:58:16 maxv Exp $");
+
+#ifdef ARMV81_PAN
+#define PAN_ENABLE \
+ adrl x9, _C_LABEL(aarch64_pan_enabled) ; \
+ ldr w9, [x9] ; \
+ cbz w9, 666f ; \
+ msr pan, #1 ; \
+666:
+#define PAN_DISABLE \
+ adrl x9, _C_LABEL(aarch64_pan_enabled) ; \
+ ldr w9, [x9] ; \
+ cbz w9, 666f ; \
+ msr pan, #0 ; \
+666:
+#else
+#define PAN_ENABLE /* nothing */
+#define PAN_DISABLE /* nothing */
+#endif
+
+ ARMV8_DEFINE_OPTIONS
.macro enter_cpu_onfault
stp fp, lr, [sp, #-16]! /* save fp, lr */
@@ -55,6 +75,7 @@
mov x0, x19 /* x0 = x19 = arg0 */
mov x1, x20 /* x1 = x20 = arg1 */
+ PAN_DISABLE /* disable PAN */
.endm
.macro exit_cpu_onfault
@@ -63,6 +84,7 @@
ldr x0, [x0, #CI_CURLWP] /* x0 = curlwp */
str xzr, [x0, #L_MD_ONFAULT] /* lwp->l_md_onfault = NULL */
9:
+ PAN_ENABLE /* enable PAN */
add sp, sp, #FB_T_SIZE /* pop stack */
ldp x19, x20, [sp], #16 /* restore x19, x20 */
ldp fp, lr, [sp], #16 /* restore fp, lr */
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/cpufunc.c
--- a/sys/arch/aarch64/aarch64/cpufunc.c Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/cpufunc.c Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.c,v 1.23 2020/07/04 04:59:36 rin Exp $ */
+/* $NetBSD: cpufunc.c,v 1.24 2020/08/02 06:58:16 maxv Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -30,7 +30,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.23 2020/07/04 04:59:36 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.24 2020/08/02 06:58:16 maxv Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -50,6 +50,7 @@
u_int aarch64_cache_vindexsize;
u_int aarch64_cache_prefer_mask;
+int aarch64_pan_enabled __read_mostly;
int aarch64_pac_enabled __read_mostly;
/* cache info per cluster. the same cluster has the same cache configuration? */
@@ -474,6 +475,36 @@
return 0;
}
+void
+aarch64_pan_init(int primary)
+{
+#ifdef ARMV81_PAN
+ uint64_t reg, sctlr;
+
+ /* CPU0 does the detection. */
+ if (primary) {
+ reg = reg_id_aa64mmfr1_el1_read();
+ if (__SHIFTOUT(reg, ID_AA64MMFR1_EL1_PAN) !=
+ ID_AA64MMFR1_EL1_PAN_NONE)
+ aarch64_pan_enabled = 1;
+ }
+
+ if (!aarch64_pan_enabled)
+ return;
+
+ /*
+ * On an exception to EL1, have the CPU set the PAN bit automatically.
+ * This ensures PAN is enabled each time the kernel is entered.
+ */
+ sctlr = reg_sctlr_el1_read();
+ sctlr &= ~SCTLR_SPAN;
+ reg_sctlr_el1_write(sctlr);
+
+ /* Set the PAN bit right now. */
+ reg_pan_write(1);
+#endif
+}
+
/*
* In order to avoid inconsistencies with pointer authentication
* in this function itself, the caller must enable PAC according
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/db_interface.c
--- a/sys/arch/aarch64/aarch64/db_interface.c Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/db_interface.c Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.7 2019/01/27 02:08:36 pgoyette Exp $ */
+/* $NetBSD: db_interface.c,v 1.8 2020/08/02 06:58:16 maxv Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.7 2019/01/27 02:08:36 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.8 2020/08/02 06:58:16 maxv Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -67,6 +67,9 @@
}
lastpage = atop((vaddr_t)src);
+ if (aarch64_pan_enabled)
+ reg_pan_write(0); /* disable PAN */
+
tmp = (uintptr_t)src | (uintptr_t)data;
if ((size >= 8) && ((tmp & 7) == 0)) {
*(uint64_t *)data = *(const uint64_t *)src;
@@ -87,6 +90,9 @@
*data++ = *src++;
size--;
}
+
+ if (aarch64_pan_enabled)
+ reg_pan_write(1); /* enable PAN */
}
}
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/fault.c
--- a/sys/arch/aarch64/aarch64/fault.c Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/fault.c Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fault.c,v 1.14 2020/07/08 03:45:13 ryo Exp $ */
+/* $NetBSD: fault.c,v 1.15 2020/08/02 06:58:16 maxv Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.14 2020/07/08 03:45:13 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.15 2020/08/02 06:58:16 maxv Exp $");
#include "opt_compat_netbsd32.h"
#include "opt_ddb.h"
@@ -136,6 +136,7 @@
vm_prot_t ftype;
int error = 0, len;
const bool user = IS_SPSR_USER(tf->tf_spsr) ? true : false;
+ bool is_pan_trap = false;
bool fatalabort;
const char *faultstr;
@@ -191,6 +192,16 @@
}
#endif
+ if (__predict_false(!user && (map != kernel_map) &&
+ (tf->tf_spsr & SPSR_PAN))) {
+ /*
+ * We were in kernel mode, faulted on a user address,
+ * and had PAN enabled. This is a fatal fault.
+ */
+ is_pan_trap = true;
+ goto handle_fault;
+ }
+
/* reference/modified emulation */
if (pmap_fault_fixup(map->pmap, va, ftype, user)) {
UVMHIST_LOG(pmaphist, "fixed: va=%016llx", tf->tf_far, 0, 0, 0);
@@ -218,6 +229,7 @@
return;
}
+ handle_fault:
fsc = __SHIFTOUT(esr, ESR_ISS_DATAABORT_DFSC); /* also IFSC */
if (user) {
if (!fatalabort) {
@@ -326,6 +338,10 @@
len += snprintf(panicinfo + len, sizeof(panicinfo) - len,
", State 2 Fault");
+ if (is_pan_trap)
+ len += snprintf(panicinfo + len, sizeof(panicinfo) - len,
+ ", PAN Set");
+
len += snprintf(panicinfo + len, sizeof(panicinfo) - len,
": pc %016"PRIxREGISTER, tf->tf_pc);
diff -r a497a50cacf9 -r a9ff7dfc3d34 sys/arch/aarch64/aarch64/fusu.S
--- a/sys/arch/aarch64/aarch64/fusu.S Sun Aug 02 06:51:47 2020 +0000
+++ b/sys/arch/aarch64/aarch64/fusu.S Sun Aug 02 06:58:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fusu.S,v 1.6 2019/04/06 03:06:24 thorpej Exp $ */
+/* $NetBSD: fusu.S,v 1.7 2020/08/02 06:58:16 maxv Exp $ */
/*-
* Copyright (c) 2014, 2019 The NetBSD Foundation, Inc.
@@ -32,7 +32,27 @@
#include <aarch64/asm.h>
#include "assym.h"
-RCSID("$NetBSD: fusu.S,v 1.6 2019/04/06 03:06:24 thorpej Exp $");
+RCSID("$NetBSD: fusu.S,v 1.7 2020/08/02 06:58:16 maxv Exp $");
+
+#ifdef ARMV81_PAN
+#define PAN_ENABLE \
+ adrl x9, _C_LABEL(aarch64_pan_enabled) ; \
+ ldr w9, [x9] ; \
+ cbz w9, 666f ; \
+ msr pan, #1 ; \
+666:
+#define PAN_DISABLE \
+ adrl x9, _C_LABEL(aarch64_pan_enabled) ; \
+ ldr w9, [x9] ; \
+ cbz w9, 666f ; \
+ msr pan, #0 ; \
+666:
+#else
+#define PAN_ENABLE /* nothing */
+#define PAN_DISABLE /* nothing */
+#endif
+
+ ARMV8_DEFINE_OPTIONS
.macro enter_cpu_onfault
stp fp, lr, [sp, #-16]! /* save fp, lr */
@@ -47,6 +67,8 @@
mov x0, sp /* x0 = faultbuf */
bl cpu_set_onfault /* x0 = cpu_set_onfault() */
cbnz x0, 9f /* return if error */
+
+ PAN_DISABLE /* disable PAN */
.endm
.macro exit_cpu_onfault
@@ -55,6 +77,7 @@
ldr x1, [x1, #CI_CURLWP] /* x1 = curlwp */
str xzr, [x1, #L_MD_ONFAULT] /* lwp->l_md_onfault = NULL */
Home |
Main Index |
Thread Index |
Old Index