summaryrefslogtreecommitdiff
path: root/sys/arch/arm64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-08-17 08:09:04 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-08-17 08:09:04 +0000
commit5ebf90b5ba926a98b72d64850ba4f6507c9c158d (patch)
treea9fdd1614488a10803a1c2a455a084e9bad0c6a0 /sys/arch/arm64
parent1944a8bb6965ec88d9275f0d64e0d36616a63068 (diff)
Panic on an attempt to access user-space unless it is done using
an "unpriviliged" load/store instruction. This makes sure we catch PAN violations and might even catch some incorrect user-space access cases on systems without PAN. ok drahn@, jsg@
Diffstat (limited to 'sys/arch/arm64')
-rw-r--r--sys/arch/arm64/arm64/trap.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/sys/arch/arm64/arm64/trap.c b/sys/arch/arm64/arm64/trap.c
index 23b5bd0f793..4f0e4aa2fd5 100644
--- a/sys/arch/arm64/arm64/trap.c
+++ b/sys/arch/arm64/arm64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.27 2020/01/06 12:37:30 kettenis Exp $ */
+/* $OpenBSD: trap.c,v 1.28 2020/08/17 08:09:03 kettenis Exp $ */
/*-
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
@@ -65,6 +65,14 @@ void do_el0_error(struct trapframe *);
void dumpregs(struct trapframe*);
+/* Check whether we're executing an unprivileged load/store instruction. */
+static inline int
+is_unpriv_ldst(uint64_t elr)
+{
+ uint32_t insn = *(uint32_t *)elr;
+ return ((insn & 0x3f200c00) == 0x38000800);
+}
+
static void
data_abort(struct trapframe *frame, uint64_t esr, uint64_t far,
int lower, int exe)
@@ -104,8 +112,18 @@ data_abort(struct trapframe *frame, uint64_t esr, uint64_t far,
/* The top bit tells us which range to use */
if ((far >> 63) == 1)
map = kernel_map;
- else
+ else {
+ /*
+ * Only allow user-space access using
+ * unprivileged load/store instructions.
+ */
+ if (!is_unpriv_ldst(frame->tf_elr)) {
+ panic("attempt to access user address"
+ " 0x%llx from EL1", far);
+ }
+
map = &p->p_vmspace->vm_map;
+ }
}
if (exe)