[PATCH kvm-unit-tests 6/6] Add leak scenario to virt_x2apic_mode_test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Marc Orr <marcorr@xxxxxxxxxx>

While working on virt_x2apic_mode_test, we noticed that KVM allows for a
buggy or malicious L1 to get at L0's x2APIC MSRs via nested. The issue
is in KVM's nested_vmx_prepare_msr_bitmap() function. Specifically, an L1
can execute the following sequence:

1. WRMSR(IA32_SPEC_CTRL, 1), which causes the spec_ctrl variable, in
nested_vmx_prepare_msr_bitmap() to become true.
2. Clear "virtualize x2APIC mode"
3. Set "APIC-register virualization"

Then, KVM will copy L1's MSR bitmap for the x2APIC MSR range into L0,
and run L2 with "Virtualize x2APIC mode" disabled, which gives L2
unfettered access to L0's x2APIC msrs.

Thus, this patch extends virt_x2apic_mode_test with a test case for this
scenario.

Note, this patch was used to discover and fix the issue described in the
KVM patch titled "KVM: x86: nVMX: close leak of L0's x2APIC MSRs".

Signed-off-by: Marc Orr <marcorr@xxxxxxxxxx>
Reviewed-by: Jim Mattson <jmattson@xxxxxxxxxx>
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 lib/x86/processor.h |  5 +++++
 x86/vmexit.c        |  5 -----
 x86/vmx_tests.c     | 31 +++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 6f77148..a4ef315 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -487,4 +487,9 @@ static inline void flush_tlb(void)
 	write_cr4(cr4);
 }
 
+static inline int has_spec_ctrl(void)
+{
+    return !!(cpuid_indexed(7,0).d & (1 << 26));
+}
+
 #endif
diff --git a/x86/vmexit.c b/x86/vmexit.c
index c12dd24..f094f53 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -417,11 +417,6 @@ static void tscdeadline(void)
 	while (x == 0) barrier();
 }
 
-static int has_spec_ctrl(void)
-{
-    return !!(cpuid_indexed(7,0).d & (1 << 26));
-}
-
 static void wr_ibrs_msr(void)
 {
 	wrmsr(MSR_IA32_SPEC_CTRL, 1);
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 12d80df..868f284 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -6106,6 +6106,27 @@ struct virt_x2apic_mode_test_case virt_x2apic_mode_tests[] = {
 			},
 		},
 	},
+
+	/*
+	 * Disable "Virtualize x2APIC mode", disable x2APIC MSR intercepts, and
+	 * enable "APIC-register virtualization" --> L2 gets L1's x2APIC MSRs.
+	 */
+	{
+		.name = "Baseline",
+		.virt_x2apic_mode_config = {
+			.virtual_interrupt_delivery = true,
+			.use_msr_bitmaps = true,
+			.disable_x2apic_msr_intercepts = true,
+			.disable_x2apic = false,
+			.apic_reg_virt_config = {
+				.apic_register_virtualization = true,
+				.use_tpr_shadow = true,
+				.virtualize_apic_accesses = false,
+				.virtualize_x2apic_mode = false,
+				.activate_secondary_controls = true,
+			},
+		},
+	},
 };
 
 enum X2apic_op {
@@ -6423,6 +6444,16 @@ static void virt_x2apic_mode_test(void)
 	struct virt_x2apic_mode_guest_args *args = &virt_x2apic_mode_guest_args;
 
 	/*
+	 * This is to exercise an issue in KVM's logic to merge L0's and L1's
+	 * MSR bitmaps. Previously, an L1 could get at L0's x2APIC MSRs by
+	 * writing the IA32_SPEC_CTRL MSR or the IA32_PRED_CMD MSRs. KVM would
+	 * then proceed to manipulate the MSR bitmaps, as if VMCS12 had the
+	 * "Virtualize x2APIC mod" control set, even when it didn't.
+	 */
+	if (has_spec_ctrl())
+		wrmsr(MSR_IA32_SPEC_CTRL, 1);
+
+	/*
 	 * Check that VMCS12 supports:
 	 *   - "Virtual-APIC address", indicated by "use TPR shadow"
 	 *   - "MSR-bitmap address", indicated by "use MSR bitmaps"
-- 
1.8.3.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux