Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Paolo Bonzini:
"Two nested virtualization fixes for AMD processors"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl (CVE-2021-3653)

+17 -7
+2
arch/x86/include/asm/svm.h
··· 184 184 #define V_IGN_TPR_SHIFT 20 185 185 #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT) 186 186 187 + #define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK) 188 + 187 189 #define V_INTR_MASKING_SHIFT 24 188 190 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT) 189 191
+10 -3
arch/x86/kvm/svm/nested.c
··· 158 158 /* If SMI is not intercepted, ignore guest SMI intercept as well */ 159 159 if (!intercept_smi) 160 160 vmcb_clr_intercept(c, INTERCEPT_SMI); 161 + 162 + vmcb_set_intercept(c, INTERCEPT_VMLOAD); 163 + vmcb_set_intercept(c, INTERCEPT_VMSAVE); 161 164 } 162 165 163 166 static void copy_vmcb_control_area(struct vmcb_control_area *dst, ··· 506 503 507 504 static void nested_vmcb02_prepare_control(struct vcpu_svm *svm) 508 505 { 509 - const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK; 506 + const u32 int_ctl_vmcb01_bits = 507 + V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK; 508 + 509 + const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK; 510 + 510 511 struct kvm_vcpu *vcpu = &svm->vcpu; 511 512 512 513 /* ··· 542 535 vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset; 543 536 544 537 svm->vmcb->control.int_ctl = 545 - (svm->nested.ctl.int_ctl & ~mask) | 546 - (svm->vmcb01.ptr->control.int_ctl & mask); 538 + (svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) | 539 + (svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits); 547 540 548 541 svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext; 549 542 svm->vmcb->control.int_vector = svm->nested.ctl.int_vector;
+5 -4
arch/x86/kvm/svm/svm.c
··· 1589 1589 1590 1590 static void svm_clear_vintr(struct vcpu_svm *svm) 1591 1591 { 1592 - const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK; 1593 1592 svm_clr_intercept(svm, INTERCEPT_VINTR); 1594 1593 1595 1594 /* Drop int_ctl fields related to VINTR injection. */ 1596 - svm->vmcb->control.int_ctl &= mask; 1595 + svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK; 1597 1596 if (is_guest_mode(&svm->vcpu)) { 1598 - svm->vmcb01.ptr->control.int_ctl &= mask; 1597 + svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK; 1599 1598 1600 1599 WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) != 1601 1600 (svm->nested.ctl.int_ctl & V_TPR_MASK)); 1602 - svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask; 1601 + 1602 + svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & 1603 + V_IRQ_INJECTION_BITS_MASK; 1603 1604 } 1604 1605 1605 1606 vmcb_mark_dirty(svm->vmcb, VMCB_INTR);