diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-08-17 08:09:04 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-08-17 08:09:04 +0000 |
commit | 5ebf90b5ba926a98b72d64850ba4f6507c9c158d (patch) | |
tree | a9fdd1614488a10803a1c2a455a084e9bad0c6a0 /sys | |
parent | 1944a8bb6965ec88d9275f0d64e0d36616a63068 (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')
-rw-r--r-- | sys/arch/arm64/arm64/trap.c | 22 |
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) |