Merge branch 'cve-2019-3016' into kvm-next-5.6
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 30 Jan 2020 17:47:38 +0000 (18:47 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 30 Jan 2020 17:47:59 +0000 (18:47 +0100)
From Boris Ostrovsky:

The KVM hypervisor may provide a guest with ability to defer remote TLB
flush when the remote VCPU is not running. When this feature is used,
the TLB flush will happen only when the remote VPCU is scheduled to run
again. This will avoid unnecessary (and expensive) IPIs.

Under certain circumstances, when a guest initiates such deferred action,
the hypervisor may miss the request. It is also possible that the guest
may mistakenly assume that it has already marked remote VCPU as needing
a flush when in fact that request had already been processed by the
hypervisor. In both cases this will result in an invalid translation
being present in a vCPU, potentially allowing accesses to memory locations
in that guest's address space that should not be accessible.

Note that only intra-guest memory is vulnerable.

The five patches address both of these problems:
1. The first patch makes sure the hypervisor doesn't accidentally clear
a guest's remote flush request
2. The rest of the patches prevent the race between hypervisor
acknowledging a remote flush request and guest issuing a new one.

Conflicts:
arch/x86/kvm/x86.c [move from kvm_arch_vcpu_free to kvm_arch_vcpu_destroy]

1  2 
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/x86.c
include/linux/kvm_host.h
virt/kvm/kvm_main.c

Simple merge
index 7e118883d8f1d5ec8baaf61fdff24bf9bd28e4fc,a0381ec905cee1f70204b005dcdb1055edd1f0a3..0b0b143f0ab612cbb7e8b8a120dca27c1c085562
@@@ -9325,26 -9159,13 +9332,29 @@@ void kvm_arch_vcpu_postcreate(struct kv
  
  void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
  {
 -      vcpu->arch.apf.msr_val = 0;
++      struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache;
 +      int idx;
  
 -      vcpu_load(vcpu);
 -      kvm_mmu_unload(vcpu);
 -      vcpu_put(vcpu);
++      kvm_release_pfn(cache->pfn, cache->dirty, cache);
++
 +      kvmclock_reset(vcpu);
  
        kvm_x86_ops->vcpu_free(vcpu);
 +
 +      free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);
 +      kmem_cache_free(x86_fpu_cache, vcpu->arch.user_fpu);
 +      kmem_cache_free(x86_fpu_cache, vcpu->arch.guest_fpu);
 +
 +      kvm_hv_vcpu_uninit(vcpu);
 +      kvm_pmu_destroy(vcpu);
 +      kfree(vcpu->arch.mce_banks);
 +      kvm_free_lapic(vcpu);
 +      idx = srcu_read_lock(&vcpu->kvm->srcu);
 +      kvm_mmu_destroy(vcpu);
 +      srcu_read_unlock(&vcpu->kvm->srcu, idx);
 +      free_page((unsigned long)vcpu->arch.pio_data);
 +      if (!lapic_in_kernel(vcpu))
 +              static_key_slow_dec(&kvm_no_apic_vcpu);
  }
  
  void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
index 6d5331b0d9378b5c04014b9a62b7169d5a8b792d,71cb9cc105f0a57a1db65a0fd2bfdcc3ac3313ce..e89eb67356cb39b225cbfff924c1a41e49197006
@@@ -720,8 -723,11 +720,9 @@@ void kvm_set_pfn_dirty(kvm_pfn_t pfn)
  void kvm_set_pfn_accessed(kvm_pfn_t pfn);
  void kvm_get_pfn(kvm_pfn_t pfn);
  
+ void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache);
  int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
                        int len);
 -int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
 -                        unsigned long len);
  int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len);
  int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
                           void *data, unsigned long len);
Simple merge