mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
Two nested virtualization fixes for AMD processors.
-----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmEabicUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroObjgf7BjKq8zyDbS1NyTW+FCaPQk5x4zy6 0EI521qJNoWMU8p9O7B4EUFJsLr4Oq7mIanact6hPSmctdWa2CxGi/FRG5QQTIpQ 8Tb2UyPPYn98OTLnM1SBfhuix4QnnYX73IRkklzCFE3Prg+XEjUoTzORVhhioC+k sD0cdYEJczsEQ9Boic+6LKNVGs7WHqsVWSruPoEPevZhvl5+RKrmbkJMxyB6G+xF EVLmxfuiU4BurRzACHBEghlAWbaqQUVHampCI0/ppH2Fb5RMviTJK0Xcbj04B7Gx NH6l5VHTBW7LXiAxcF+oNWLZlmhmWzsVSmw4P01ZuFXlohW3rtPm5WjUiw== =+7g8 -----END PGP SIGNATURE----- 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)
This commit is contained in:
commit
02a3715449
3 changed files with 17 additions and 7 deletions
|
@ -184,6 +184,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
||||||
#define V_IGN_TPR_SHIFT 20
|
#define V_IGN_TPR_SHIFT 20
|
||||||
#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
|
#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
|
||||||
|
|
||||||
|
#define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK)
|
||||||
|
|
||||||
#define V_INTR_MASKING_SHIFT 24
|
#define V_INTR_MASKING_SHIFT 24
|
||||||
#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
|
#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
|
||||||
/* If SMI is not intercepted, ignore guest SMI intercept as well */
|
/* If SMI is not intercepted, ignore guest SMI intercept as well */
|
||||||
if (!intercept_smi)
|
if (!intercept_smi)
|
||||||
vmcb_clr_intercept(c, INTERCEPT_SMI);
|
vmcb_clr_intercept(c, INTERCEPT_SMI);
|
||||||
|
|
||||||
|
vmcb_set_intercept(c, INTERCEPT_VMLOAD);
|
||||||
|
vmcb_set_intercept(c, INTERCEPT_VMSAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_vmcb_control_area(struct vmcb_control_area *dst,
|
static void copy_vmcb_control_area(struct vmcb_control_area *dst,
|
||||||
|
@ -503,7 +506,11 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12
|
||||||
|
|
||||||
static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
||||||
{
|
{
|
||||||
const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK;
|
const u32 int_ctl_vmcb01_bits =
|
||||||
|
V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
|
||||||
|
|
||||||
|
const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
|
||||||
|
|
||||||
struct kvm_vcpu *vcpu = &svm->vcpu;
|
struct kvm_vcpu *vcpu = &svm->vcpu;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -535,8 +542,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
||||||
vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset;
|
vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset;
|
||||||
|
|
||||||
svm->vmcb->control.int_ctl =
|
svm->vmcb->control.int_ctl =
|
||||||
(svm->nested.ctl.int_ctl & ~mask) |
|
(svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) |
|
||||||
(svm->vmcb01.ptr->control.int_ctl & mask);
|
(svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits);
|
||||||
|
|
||||||
svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext;
|
svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext;
|
||||||
svm->vmcb->control.int_vector = svm->nested.ctl.int_vector;
|
svm->vmcb->control.int_vector = svm->nested.ctl.int_vector;
|
||||||
|
|
|
@ -1589,17 +1589,18 @@ static void svm_set_vintr(struct vcpu_svm *svm)
|
||||||
|
|
||||||
static void svm_clear_vintr(struct vcpu_svm *svm)
|
static void svm_clear_vintr(struct vcpu_svm *svm)
|
||||||
{
|
{
|
||||||
const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK;
|
|
||||||
svm_clr_intercept(svm, INTERCEPT_VINTR);
|
svm_clr_intercept(svm, INTERCEPT_VINTR);
|
||||||
|
|
||||||
/* Drop int_ctl fields related to VINTR injection. */
|
/* Drop int_ctl fields related to VINTR injection. */
|
||||||
svm->vmcb->control.int_ctl &= mask;
|
svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
|
||||||
if (is_guest_mode(&svm->vcpu)) {
|
if (is_guest_mode(&svm->vcpu)) {
|
||||||
svm->vmcb01.ptr->control.int_ctl &= mask;
|
svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
|
||||||
|
|
||||||
WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
|
WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
|
||||||
(svm->nested.ctl.int_ctl & V_TPR_MASK));
|
(svm->nested.ctl.int_ctl & V_TPR_MASK));
|
||||||
svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask;
|
|
||||||
|
svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
|
||||||
|
V_IRQ_INJECTION_BITS_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
|
vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
|
||||||
|
|
Loading…
Add table
Reference in a new issue