[x86] kvm:vmx: more complete state update on APICv on/off (CVE-2016-4440)

This commit is contained in:
Ben Hutchings 2016-05-23 02:35:36 +01:00
parent 327c921aa7
commit 5bec7a0097
3 changed files with 103 additions and 0 deletions

1
debian/changelog vendored
View File

@ -94,6 +94,7 @@ linux (4.5.5-1) UNRELEASED; urgency=medium
* aufs: Update support patches to aufs4.5-20160523
- mmap: Fix use-after-free in remap_file_pages(2)
* Revert "stmmac: Fix 'eth0: No PHY found' regression" (Closes: #823493)
* [x86] kvm:vmx: more complete state update on APICv on/off (CVE-2016-4440)
-- Salvatore Bonaccorso <carnil@debian.org> Sat, 21 May 2016 16:47:59 +0200

View File

@ -0,0 +1,101 @@
From: Roman Kagan <rkagan@virtuozzo.com>
Subject: kvm:vmx: more complete state update on APICv on/off
Date: Wed, 18 May 2016 17:48:20 +0300
Origin: http://article.gmane.org/gmane.comp.emulators.kvm.devel/152191
The function to update APICv on/off state (in particular, to deactivate
it when enabling Hyper-V SynIC), used to be incomplete: it didn't adjust
APICv-related fields among secondary processor-based VM-execution
controls.
As a result, Windows 2012 guests would get stuck when SynIC-based
auto-EOI interrupt intersected with e.g. an IPI in the guest.
In addition, the MSR intercept bitmap wasn't updated to correspond to
whether "virtualize x2APIC mode" was enabled. This path used not to be
triggered, since Windows didn't use x2APIC but rather their own
synthetic APIC access MSRs; however it represented a security risk
because the guest running in a SynIC-enabled VM could switch to x2APIC
and thus obtain direct access to host APIC MSRs (thanks to Yang Zhang
<yang.zhang.wz@gmail.com> for spotting this).
The patch fixes those omissions.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Cc: Steve Rutherford <srutherford@google.com>
Cc: Yang Zhang <yang.zhang.wz@gmail.com>
---
arch/x86/kvm/vmx.c | 48 ++++++++++++++++++++++++++++++------------------
1 file changed, 30 insertions(+), 18 deletions(-)
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2397,7 +2397,9 @@ static void vmx_set_msr_bitmap(struct kv
if (is_guest_mode(vcpu))
msr_bitmap = vmx_msr_bitmap_nested;
- else if (vcpu->arch.apic_base & X2APIC_ENABLE) {
+ else if (cpu_has_secondary_exec_ctrls() &&
+ (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) &
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
if (is_long_mode(vcpu))
msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
else
@@ -4758,6 +4760,19 @@ static void vmx_refresh_apicv_exec_ctrl(
struct vcpu_vmx *vmx = to_vmx(vcpu);
vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
+ if (cpu_has_secondary_exec_ctrls()) {
+ if (kvm_vcpu_apicv_active(vcpu))
+ vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+ else
+ vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+ }
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmx_set_msr_bitmap(vcpu);
}
static u32 vmx_exec_control(struct vcpu_vmx *vmx)
@@ -6313,23 +6328,20 @@ static __init int hardware_setup(void)
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
- if (enable_apicv) {
- for (msr = 0x800; msr <= 0x8ff; msr++)
- vmx_disable_intercept_msr_read_x2apic(msr);
-
- /* According SDM, in x2apic mode, the whole id reg is used.
- * But in KVM, it only use the highest eight bits. Need to
- * intercept it */
- vmx_enable_intercept_msr_read_x2apic(0x802);
- /* TMCCT */
- vmx_enable_intercept_msr_read_x2apic(0x839);
- /* TPR */
- vmx_disable_intercept_msr_write_x2apic(0x808);
- /* EOI */
- vmx_disable_intercept_msr_write_x2apic(0x80b);
- /* SELF-IPI */
- vmx_disable_intercept_msr_write_x2apic(0x83f);
- }
+ for (msr = 0x800; msr <= 0x8ff; msr++)
+ vmx_disable_intercept_msr_read_x2apic(msr);
+
+ /* According SDM, in x2apic mode, the whole id reg is used. But in
+ * KVM, it only use the highest eight bits. Need to intercept it */
+ vmx_enable_intercept_msr_read_x2apic(0x802);
+ /* TMCCT */
+ vmx_enable_intercept_msr_read_x2apic(0x839);
+ /* TPR */
+ vmx_disable_intercept_msr_write_x2apic(0x808);
+ /* EOI */
+ vmx_disable_intercept_msr_write_x2apic(0x80b);
+ /* SELF-IPI */
+ vmx_disable_intercept_msr_write_x2apic(0x83f);
if (enable_ept) {
kvm_mmu_set_mask_ptes(0ull,

View File

@ -139,6 +139,7 @@ bugfix/all/KVM-MTRR-remove-MSR-0x2f8.patch
bugfix/all/tipc-check-nl-sock-before-parsing-nested-attributes.patch
# ABI maintenance
bugfix/x86/kvm-vmx-more-complete-state-update-on-apicv-on-off.patch
debian/ib-fix-abi-change-in-4.5.3.patch
debian/v4l2-fix-abi-changes-in-4.5.3.patch
debian/cgroup-fix-abi-change-in-4.5.3.patch