diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2017-10-03 17:36:41 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2017-10-03 17:36:41 +0000 |
commit | 3ffe4f162ae2ff4be028798cdcd9cd02ac13a656 (patch) | |
tree | 86bd53b1a3a9bda9ce60bf51aae041d7b47d5f10 /sys/arch | |
parent | d13da36f94d8d7133aefc88a6ddd79ff6de072c1 (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.c | 6 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/locore.S | 11 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/trap.c | 14 |
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", |