KVM: x86: Handle SRCU initialization failure during page track init
commit eb7511bf9182292ef1df1082d23039e856d1ddfb upstream. Check the return of init_srcu_struct(), which can fail due to OOM, when initializing the page track mechanism. Lack of checking leads to a NULL pointer deref found by a modified syzkaller. Reported-by: TCS Robot <tcs_robot@tencent.com> Signed-off-by: Haimin Zhang <tcs_kernel@tencent.com> Message-Id: <1630636626-12262-1-git-send-email-tcs_kernel@tencent.com> [Move the call towards the beginning of kvm_arch_init_vm. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
f7ac4d24e1
commit
deb2949417
@@ -46,7 +46,7 @@ struct kvm_page_track_notifier_node {
|
|||||||
struct kvm_page_track_notifier_node *node);
|
struct kvm_page_track_notifier_node *node);
|
||||||
};
|
};
|
||||||
|
|
||||||
void kvm_page_track_init(struct kvm *kvm);
|
int kvm_page_track_init(struct kvm *kvm);
|
||||||
void kvm_page_track_cleanup(struct kvm *kvm);
|
void kvm_page_track_cleanup(struct kvm *kvm);
|
||||||
|
|
||||||
void kvm_page_track_free_memslot(struct kvm_memory_slot *slot);
|
void kvm_page_track_free_memslot(struct kvm_memory_slot *slot);
|
||||||
|
@@ -163,13 +163,13 @@ void kvm_page_track_cleanup(struct kvm *kvm)
|
|||||||
cleanup_srcu_struct(&head->track_srcu);
|
cleanup_srcu_struct(&head->track_srcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_page_track_init(struct kvm *kvm)
|
int kvm_page_track_init(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
struct kvm_page_track_notifier_head *head;
|
struct kvm_page_track_notifier_head *head;
|
||||||
|
|
||||||
head = &kvm->arch.track_notifier_head;
|
head = &kvm->arch.track_notifier_head;
|
||||||
init_srcu_struct(&head->track_srcu);
|
|
||||||
INIT_HLIST_HEAD(&head->track_notifier_list);
|
INIT_HLIST_HEAD(&head->track_notifier_list);
|
||||||
|
return init_srcu_struct(&head->track_srcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -10392,9 +10392,15 @@ void kvm_arch_free_vm(struct kvm *kvm)
|
|||||||
|
|
||||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = kvm_page_track_init(kvm);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
|
INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
|
||||||
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
|
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
|
||||||
INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
|
INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
|
||||||
@@ -10421,7 +10427,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
|||||||
INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn);
|
INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn);
|
||||||
|
|
||||||
kvm_hv_init_vm(kvm);
|
kvm_hv_init_vm(kvm);
|
||||||
kvm_page_track_init(kvm);
|
|
||||||
kvm_mmu_init_vm(kvm);
|
kvm_mmu_init_vm(kvm);
|
||||||
|
|
||||||
return kvm_x86_ops.vm_init(kvm);
|
return kvm_x86_ops.vm_init(kvm);
|
||||||
|
Reference in New Issue
Block a user