untrusted comment: signature from openbsd 6.1 base secret key
RWQEQa33SgQSEhrFVgw72xZt8W7xDl9PzxWwhdUxOWTVlA787JyHTBI2TRovt5eR4sXNLrKmwBxHJ49g6Jvpc9/blIFVLjQNowc=
OpenBSD 6.1 errata 031, October 4th, 2017:
Do not leak kernel address when restoring an invalid FPU context.
Apply by doing:
signify -Vep /etc/signify/openbsd-61-base.pub -x 031_xrstor_resume.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
Index: sys/arch/amd64/amd64/fpu.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/fpu.c,v
retrieving revision 1.33.6.2
diff -u -p -r1.33.6.2 fpu.c
--- sys/arch/amd64/amd64/fpu.c 3 Oct 2017 22:11:56 -0000 1.33.6.2
+++ sys/arch/amd64/amd64/fpu.c 4 Oct 2017 13:20:39 -0000
@@ -56,7 +56,8 @@
#include <dev/isa/isavar.h>
-void xrstor_user(struct savefpu *_addr, uint64_t _mask);
+int xrstor_user(struct savefpu *_addr, uint64_t _mask);
+void trap(struct trapframe *);
/*
* We do lazy initialization and switching using the TS bit in cr0 and the
@@ -81,7 +82,7 @@ void xrstor_user(struct savefpu *_addr,
*/
uint64_t xsave_mask;
-void fpudna(struct cpu_info *);
+void fpudna(struct cpu_info *, struct trapframe *);
static int x86fpflags_to_siginfo(u_int32_t);
/*
@@ -195,7 +196,7 @@ x86fpflags_to_siginfo(u_int32_t flags)
* saved state.
*/
void
-fpudna(struct cpu_info *ci)
+fpudna(struct cpu_info *ci, struct trapframe *frame)
{
struct savefpu *sfp;
struct proc *p;
@@ -256,7 +257,12 @@ fpudna(struct cpu_info *ci)
p->p_md.md_flags |= MDP_USEDFPU;
} else {
if (xsave_mask) {
- xrstor_user(sfp, xsave_mask);
+ if (xrstor_user(sfp, xsave_mask)) {
+ fpusave_proc(p, 0); /* faulted */
+ frame->tf_trapno = T_PROTFLT;
+ trap(frame);
+ return;
+ }
} else {
static double zero = 0.0;
Index: sys/arch/amd64/amd64/locore.S
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/locore.S,v
retrieving revision 1.84.4.1
diff -u -p -r1.84.4.1 locore.S
--- sys/arch/amd64/amd64/locore.S 3 Oct 2017 22:11:56 -0000 1.84.4.1
+++ sys/arch/amd64/amd64/locore.S 4 Oct 2017 13:20:39 -0000
@@ -1210,6 +1210,10 @@ ENTRY(xrstor_user)
.globl xrstor_fault
xrstor_fault:
xrstor (%rdi)
+ xorl %eax, %eax
+ ret
+ENTRY(xrstor_resume)
+ movl $1, %eax
ret
ENTRY(pagezero)
Index: sys/arch/amd64/amd64/trap.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/trap.c,v
retrieving revision 1.53.4.2
diff -u -p -r1.53.4.2 trap.c
--- sys/arch/amd64/amd64/trap.c 3 Oct 2017 22:11:56 -0000 1.53.4.2
+++ sys/arch/amd64/amd64/trap.c 4 Oct 2017 13:20:39 -0000
@@ -148,7 +148,8 @@ trap(struct trapframe *frame)
struct proc *p = curproc;
int type = (int)frame->tf_trapno;
struct pcb *pcb;
- extern char doreti_iret[], resume_iret[], xrstor_fault[];
+ extern char doreti_iret[], resume_iret[];
+ extern char xrstor_fault[], xrstor_resume[];
caddr_t onfault;
int error;
uint64_t cr2;
@@ -228,8 +229,8 @@ trap(struct trapframe *frame)
* instruction that faulted.
*/
if (frame->tf_rip == (u_int64_t)xrstor_fault && p != NULL) {
- fpusave_proc(p, 0);
- goto user_trap;
+ frame->tf_rip = (u_int64_t)xrstor_resume;
+ return;
}
case T_SEGNPFLT:
case T_ALIGNFLT:
@@ -260,7 +261,6 @@ 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",
Index: sys/arch/amd64/amd64/vector.S
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/vector.S,v
retrieving revision 1.47.4.1
diff -u -p -r1.47.4.1 vector.S
--- sys/arch/amd64/amd64/vector.S 26 Aug 2017 00:14:20 -0000 1.47.4.1
+++ sys/arch/amd64/amd64/vector.S 4 Oct 2017 13:20:39 -0000
@@ -127,6 +127,7 @@ IDTVEC(trap07)
cld
SMAP_CLAC
movq CPUVAR(SELF),%rdi
+ movq %rsp, %rsi
call _C_LABEL(fpudna)
INTRFASTEXIT
IDTVEC(trap08)