summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2019-03-26 19:32:48 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2019-03-26 19:32:48 +0000
commit12f76fe2ff33b12d8f83ba43c7c25117e684f785 (patch)
treef4dbd192249fffa52ddfc8a04a2d8889e3327c56 /sys
parent21964eaa67c19c3867d66d69ddc6b05d8e3b1b57 (diff)
vmm(4): On VMX, use sgdt/sidt to reset the GDT/IDT limits after exiting
the guest VM. By default, VMX sets the limits to 0xFFFF on exit, which is larger than what we want and can lead to security issues. While here, reset the LDT as well. We don't use this in OpenBSD, and VMX loads a null LDT selector on exit anyway, but resetting it here prevents any future surprises. Pointed out by Maxime Villard from NetBSD - thanks! ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/vmm.c13
-rw-r--r--sys/arch/amd64/include/cpufunc.h26
2 files changed, 36 insertions, 3 deletions
diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c
index 794bb941ae9..b6aec5ad752 100644
--- a/sys/arch/amd64/amd64/vmm.c
+++ b/sys/arch/amd64/amd64/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.232 2019/03/10 08:27:28 mlarkin Exp $ */
+/* $OpenBSD: vmm.c,v 1.233 2019/03/26 19:32:47 mlarkin Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@@ -3968,8 +3968,9 @@ vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp)
struct schedstate_percpu *spc;
struct vmx_invvpid_descriptor vid;
uint64_t eii, procbased, int_st;
- uint16_t irq;
+ uint16_t irq, ldt_sel;
u_long s;
+ struct region_descriptor gdtr, idtr;
resume = 0;
irq = vrp->vrp_irq;
@@ -4170,11 +4171,19 @@ vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp)
break;
}
+ sgdt(&gdtr);
+ sidt(&idtr);
+ sldt(&ldt_sel);
+
KERNEL_UNLOCK();
ret = vmx_enter_guest(&vcpu->vc_control_pa,
&vcpu->vc_gueststate, resume,
curcpu()->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr);
+ bare_lgdt(&gdtr);
+ lidt(&idtr);
+ lldt(ldt_sel);
+
/*
* On exit, interrupts are disabled, and we are running with
* the guest FPU state still possibly on the CPU. Save the FPU
diff --git a/sys/arch/amd64/include/cpufunc.h b/sys/arch/amd64/include/cpufunc.h
index edca45c5c2d..c72437e84dd 100644
--- a/sys/arch/amd64/include/cpufunc.h
+++ b/sys/arch/amd64/include/cpufunc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc.h,v 1.32 2019/01/20 00:53:08 mlarkin Exp $ */
+/* $OpenBSD: cpufunc.h,v 1.33 2019/03/26 19:32:46 mlarkin Exp $ */
/* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */
/*-
@@ -52,12 +52,36 @@ invlpg(u_int64_t addr)
}
static __inline void
+sidt(void *p)
+{
+ __asm volatile("sidt (%0)" : : "r" (p) : "memory");
+}
+
+static __inline void
lidt(void *p)
{
__asm volatile("lidt (%0)" : : "r" (p) : "memory");
}
static __inline void
+sgdt(void *p)
+{
+ __asm volatile("sgdt (%0)" : : "r" (p) : "memory");
+}
+
+static __inline void
+bare_lgdt(struct region_descriptor *p)
+{
+ __asm volatile("lgdt (%0)" : : "r" (p) : "memory");
+}
+
+static __inline void
+sldt(u_short *sel)
+{
+ __asm volatile("sldt (%0)" : : "r" (sel) : "memory");
+}
+
+static __inline void
lldt(u_short sel)
{
__asm volatile("lldt %0" : : "r" (sel));