summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2017-10-03 17:36:41 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2017-10-03 17:36:41 +0000
commit3ffe4f162ae2ff4be028798cdcd9cd02ac13a656 (patch)
tree86bd53b1a3a9bda9ce60bf51aae041d7b47d5f10 /sys/arch
parentd13da36f94d8d7133aefc88a6ddd79ff6de072c1 (diff)
The xrstor instruction will fault if the provided xstate data, which
is under userspace control via sigreturn, fails various consistency checks. Rather than trying to replicate the CPU's hardwired checks in C code, handle it like iretq: check in trap() whether a fault is from the problem instruction and handle it there. CPU behavior and the potential issue pointed out on Linux kernel-hardening ok mikeb@ deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/fpu.c6
-rw-r--r--sys/arch/amd64/amd64/locore.S11
-rw-r--r--sys/arch/amd64/amd64/trap.c14
3 files changed, 26 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c
index 4e8365cc694..74cd263c015 100644
--- a/sys/arch/amd64/amd64/fpu.c
+++ b/sys/arch/amd64/amd64/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.35 2017/05/29 14:19:49 mpi Exp $ */
+/* $OpenBSD: fpu.c,v 1.36 2017/10/03 17:36:40 guenther Exp $ */
/* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -55,6 +55,8 @@
#include <dev/isa/isavar.h>
+void xrstor_user(struct savefpu *_addr, uint64_t _mask);
+
/*
* We do lazy initialization and switching using the TS bit in cr0 and the
* MDP_USEDFPU bit in mdproc.
@@ -253,7 +255,7 @@ fpudna(struct cpu_info *ci)
p->p_md.md_flags |= MDP_USEDFPU;
} else {
if (xsave_mask) {
- xrstor(sfp, xsave_mask);
+ xrstor_user(sfp, xsave_mask);
} else {
static double zero = 0.0;
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index dbd2e2fbbaf..e0fa7144b62 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.87 2017/07/06 06:17:04 deraadt Exp $ */
+/* $OpenBSD: locore.S,v 1.88 2017/10/03 17:36:40 guenther Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -691,6 +691,15 @@ _C_LABEL(doreti_iret):
iretq
#endif /* !defined(GPROF) && defined(DDBPROF) */
+ENTRY(xrstor_user)
+ movq %rsi, %rdx
+ movl %esi, %eax
+ shrq $32, %rdx
+ .globl xrstor_fault
+xrstor_fault:
+ xrstor (%rdi)
+ ret
+
ENTRY(pagezero)
movq $-PAGE_SIZE,%rdx
subq %rdx,%rdi
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
index 726bea4394e..66278f198e8 100644
--- a/sys/arch/amd64/amd64/trap.c
+++ b/sys/arch/amd64/amd64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.58 2017/09/16 02:03:40 guenther Exp $ */
+/* $OpenBSD: trap.c,v 1.59 2017/10/03 17:36:40 guenther Exp $ */
/* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */
/*-
@@ -144,7 +144,7 @@ trap(struct trapframe *frame)
struct proc *p = curproc;
int type = (int)frame->tf_trapno;
struct pcb *pcb;
- extern char doreti_iret[], resume_iret[];
+ extern char doreti_iret[], resume_iret[], xrstor_fault[];
caddr_t onfault;
int error;
uint64_t cr2;
@@ -204,6 +204,15 @@ trap(struct trapframe *frame)
/*NOTREACHED*/
case T_PROTFLT:
+ /*
+ * Check for xrstor faulting because of invalid xstate
+ * We do this by looking at the address of the
+ * instruction that faulted.
+ */
+ if (frame->tf_rip == (u_int64_t)xrstor_fault && p != NULL) {
+ fpusave_proc(p, 0);
+ goto user_trap;
+ }
case T_SEGNPFLT:
case T_ALIGNFLT:
case T_TSSFLT:
@@ -231,6 +240,7 @@ copyfault:
case T_TSSFLT|T_USER:
case T_SEGNPFLT|T_USER:
case T_STKFLT|T_USER:
+user_trap:
#ifdef TRAP_SIGDEBUG
printf("pid %d (%s): %s at rip %llx addr %llx\n",
p->p_p->ps_pid, p->p_p->ps_comm, "BUS",