aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWanpeng Li <wanpengli@tencent.com>2019-09-16 03:42:32 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-09-24 07:37:27 -0400
commita073d7e3ad687a7ef32b65affe80faa7ce89bf92 (patch)
tree4531a8323ac64630a06772ac0a57a6189c353cb3
parent319109a2d0dde8672323efcf909740c2c6e98be4 (diff)
KVM: hyperv: Fix Direct Synthetic timers assert an interrupt w/o lapic_in_kernel
Reported by syzkaller: kasan: GPF could be caused by NULL-ptr deref or user memory access general protection fault: 0000 [#1] PREEMPT SMP KASAN RIP: 0010:__apic_accept_irq+0x46/0x740 arch/x86/kvm/lapic.c:1029 Call Trace: kvm_apic_set_irq+0xb4/0x140 arch/x86/kvm/lapic.c:558 stimer_notify_direct arch/x86/kvm/hyperv.c:648 [inline] stimer_expiration arch/x86/kvm/hyperv.c:659 [inline] kvm_hv_process_stimers+0x594/0x1650 arch/x86/kvm/hyperv.c:686 vcpu_enter_guest+0x2b2a/0x54b0 arch/x86/kvm/x86.c:7896 vcpu_run+0x393/0xd40 arch/x86/kvm/x86.c:8152 kvm_arch_vcpu_ioctl_run+0x636/0x900 arch/x86/kvm/x86.c:8360 kvm_vcpu_ioctl+0x6cf/0xaf0 arch/x86/kvm/../../../virt/kvm/kvm_main.c:2765 The testcase programs HV_X64_MSR_STIMERn_CONFIG/HV_X64_MSR_STIMERn_COUNT, in addition, there is no lapic in the kernel, the counters value are small enough in order that kvm_hv_process_stimers() inject this already-expired timer interrupt into the guest through lapic in the kernel which triggers the NULL deferencing. This patch fixes it by don't advertise direct mode synthetic timers and discarding the inject when lapic is not in kernel. syzkaller source: https://syzkaller.appspot.com/x/repro.c?x=1752fe0a600000 Reported-by: syzbot+dff25ee91f0c7d5c1695@syzkaller.appspotmail.com Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Signed-off-by: Wanpeng Li <wanpengli@tencent.com> Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/hyperv.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index fff790a3f4ee..c0867b0aae3e 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -645,7 +645,9 @@ static int stimer_notify_direct(struct kvm_vcpu_hv_stimer *stimer)
645 .vector = stimer->config.apic_vector 645 .vector = stimer->config.apic_vector
646 }; 646 };
647 647
648 return !kvm_apic_set_irq(vcpu, &irq, NULL); 648 if (lapic_in_kernel(vcpu))
649 return !kvm_apic_set_irq(vcpu, &irq, NULL);
650 return 0;
649} 651}
650 652
651static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) 653static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer)
@@ -1852,7 +1854,13 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
1852 1854
1853 ent->edx |= HV_FEATURE_FREQUENCY_MSRS_AVAILABLE; 1855 ent->edx |= HV_FEATURE_FREQUENCY_MSRS_AVAILABLE;
1854 ent->edx |= HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE; 1856 ent->edx |= HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE;
1855 ent->edx |= HV_STIMER_DIRECT_MODE_AVAILABLE; 1857
1858 /*
1859 * Direct Synthetic timers only make sense with in-kernel
1860 * LAPIC
1861 */
1862 if (lapic_in_kernel(vcpu))
1863 ent->edx |= HV_STIMER_DIRECT_MODE_AVAILABLE;
1856 1864
1857 break; 1865 break;
1858 1866