diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-27 11:53:50 -0400 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-28 08:08:02 -0400 |
| commit | 2beb6dad2e8f95d710159d5befb390e4f62ab5cf (patch) | |
| tree | de7330624e1508cc44fd21799cc689a7038c9a86 | |
| parent | 7ad658b693536741c37b16aeb07840a2ce75f5b9 (diff) | |
KVM: x86: cleanup the page tracking SRCU instance
SRCU uses a delayed work item. Skip cleaning it up, and
the result is use-after-free in the work item callbacks.
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Suggested-by: Dmitry Vyukov <dvyukov@google.com>
Cc: stable@vger.kernel.org
Fixes: 0eb05bf290cfe8610d9680b49abef37febd1c38a
Reviewed-by: Xiao Guangrong <xiaoguangrong.eric@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
| -rw-r--r-- | arch/x86/include/asm/kvm_page_track.h | 1 | ||||
| -rw-r--r-- | arch/x86/kvm/page_track.c | 8 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 1 |
3 files changed, 10 insertions, 0 deletions
diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h index d74747b031ec..c4eda791f877 100644 --- a/arch/x86/include/asm/kvm_page_track.h +++ b/arch/x86/include/asm/kvm_page_track.h | |||
| @@ -46,6 +46,7 @@ struct kvm_page_track_notifier_node { | |||
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | void kvm_page_track_init(struct kvm *kvm); | 48 | void kvm_page_track_init(struct kvm *kvm); |
| 49 | void kvm_page_track_cleanup(struct kvm *kvm); | ||
| 49 | 50 | ||
| 50 | void kvm_page_track_free_memslot(struct kvm_memory_slot *free, | 51 | void kvm_page_track_free_memslot(struct kvm_memory_slot *free, |
| 51 | struct kvm_memory_slot *dont); | 52 | struct kvm_memory_slot *dont); |
diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c index 37942e419c32..60168cdd0546 100644 --- a/arch/x86/kvm/page_track.c +++ b/arch/x86/kvm/page_track.c | |||
| @@ -160,6 +160,14 @@ bool kvm_page_track_is_active(struct kvm_vcpu *vcpu, gfn_t gfn, | |||
| 160 | return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]); | 160 | return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | void kvm_page_track_cleanup(struct kvm *kvm) | ||
| 164 | { | ||
| 165 | struct kvm_page_track_notifier_head *head; | ||
| 166 | |||
| 167 | head = &kvm->arch.track_notifier_head; | ||
| 168 | cleanup_srcu_struct(&head->track_srcu); | ||
| 169 | } | ||
| 170 | |||
| 163 | void kvm_page_track_init(struct kvm *kvm) | 171 | void kvm_page_track_init(struct kvm *kvm) |
| 164 | { | 172 | { |
| 165 | struct kvm_page_track_notifier_head *head; | 173 | struct kvm_page_track_notifier_head *head; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 64697fe475c3..ccbd45ecd41a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -8158,6 +8158,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
| 8158 | kvm_free_vcpus(kvm); | 8158 | kvm_free_vcpus(kvm); |
| 8159 | kvfree(rcu_dereference_check(kvm->arch.apic_map, 1)); | 8159 | kvfree(rcu_dereference_check(kvm->arch.apic_map, 1)); |
| 8160 | kvm_mmu_uninit_vm(kvm); | 8160 | kvm_mmu_uninit_vm(kvm); |
| 8161 | kvm_page_track_cleanup(kvm); | ||
| 8161 | } | 8162 | } |
| 8162 | 8163 | ||
| 8163 | void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, | 8164 | void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, |
