Commit eb7511bf authored by Haimin Zhang's avatar Haimin Zhang Committed by Paolo Bonzini
Browse files

KVM: x86: Handle SRCU initialization failure during page track init



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: default avatarTCS Robot <tcs_robot@tencent.com>
Signed-off-by: default avatarHaimin 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: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent cd36ae87
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ struct kvm_page_track_notifier_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_free_memslot(struct kvm_memory_slot *slot);
+2 −2
Original line number Diff line number Diff line
@@ -164,13 +164,13 @@ void kvm_page_track_cleanup(struct kvm *kvm)
	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;

	head = &kvm->arch.track_notifier_head;
	init_srcu_struct(&head->track_srcu);
	INIT_HLIST_HEAD(&head->track_notifier_list);
	return init_srcu_struct(&head->track_srcu);
}

/*
+6 −1
Original line number Diff line number Diff line
@@ -11144,9 +11144,15 @@ void kvm_arch_free_vm(struct kvm *kvm)

int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
	int ret;

	if (type)
		return -EINVAL;

	ret = kvm_page_track_init(kvm);
	if (ret)
		return ret;

	INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
	INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
@@ -11179,7 +11185,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)

	kvm_apicv_init(kvm);
	kvm_hv_init_vm(kvm);
	kvm_page_track_init(kvm);
	kvm_mmu_init_vm(kvm);
	kvm_xen_init_vm(kvm);