| From 4664318f73e496cd22c71b10888e75434a123e23 Mon Sep 17 00:00:00 2001 |
| From: Haimin Zhang <tcs_kernel@tencent.com> |
| Date: Fri, 3 Sep 2021 10:37:06 +0800 |
| Subject: [PATCH] KVM: x86: Handle SRCU initialization failure during page track init |
| Git-commit: eb7511bf9182292ef1df1082d23039e856d1ddfb |
| Patch-mainline: v5.15-rc4 |
| References: stable-5.14.10 |
| |
| 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> |
| Acked-by: Takashi Iwai <tiwai@suse.de> |
| |
| |
| arch/x86/include/asm/kvm_page_track.h | 2 +- |
| arch/x86/kvm/mmu/page_track.c | 4 ++-- |
| arch/x86/kvm/x86.c | 7 ++++++- |
| 3 files changed, 9 insertions(+), 4 deletions(-) |
| |
| diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h |
| index 87bd6025d91d..6a5f3acf2b33 100644 |
| |
| |
| @@ -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); |
| diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c |
| index 91a9f7e0fd91..68e67228101d 100644 |
| |
| |
| @@ -163,13 +163,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); |
| } |
| |
| /* |
| diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c |
| index 09e01a76ab0d..6d5d6e93f5c4 100644 |
| |
| |
| @@ -11093,9 +11093,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); |
| @@ -11128,7 +11134,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); |
| |
| return static_call(kvm_x86_vm_init)(kvm); |
| -- |
| 2.26.2 |
| |