summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorChaithanya Lagisetty <nagachaithanya9911@gmail.com>2026-09-04 21:44:54 +0800
committerHuacai Chen <chenhuacai@loongson.cn>2026-09-04 21:44:54 +0800
commit910132bc7d72f26a8b288c2a38c32445a48d5be0 (patch)
tree2383eddfbd3ae80531734366f17ae393d11dae5d /arch
parent4af22177032ab2357bf551fbfcdebc8fd9f2502d (diff)
downloadlinux-910132bc7d72f26a8b288c2a38c32445a48d5be0.tar.gz
linux-910132bc7d72f26a8b288c2a38c32445a48d5be0.zip
LoongArch: KVM: Fix resource leak in kvm_loongarch_env_init() error path
kvm_loongarch_env_init() allocates the per-CPU kvm_context (vmcs) and kvm_loongarch_ops, registers the perf callbacks, and then registers the IPI/EIOINTC/PCH-PIC/DMSINTC KVM devices. If any of those device registrations fails, the function returned the error directly, leaving everything acquired so far in place: vmcs and kvm_loongarch_ops are never freed, the perf callbacks stay registered, and all previously registered KVM device operations remain registered. kvm_loongarch_init() propagates the errors without calling kvm_loongarch_env_exit(), so nothing else cleans up either. Unwind the error path in reverse order of registration, so that each failure only undoes what had actually been set up. Use the same helpers in kvm_loongarch_env_exit() to remove the device registrations during normal teardown as well. Cc: stable@vger.kernel.org Fixes: c532de5a67a7 ("LoongArch: KVM: Add IPI device support") Reviewed-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Chaithanya Lagisetty <nagachaithanya9911@gmail.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch')
-rw-r--r--arch/loongarch/kvm/main.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
index b6ddf5827c03..236523d2449d 100644
--- a/arch/loongarch/kvm/main.c
+++ b/arch/loongarch/kvm/main.c
@@ -385,27 +385,52 @@ static int kvm_loongarch_env_init(void)
/* Register LoongArch IPI interrupt controller interface. */
ret = kvm_loongarch_register_ipi_device();
if (ret)
- return ret;
+ goto err_env;
/* Register LoongArch EIOINTC interrupt controller interface. */
ret = kvm_loongarch_register_eiointc_device();
if (ret)
- return ret;
+ goto err_ipi;
/* Register LoongArch PCH-PIC interrupt controller interface. */
ret = kvm_loongarch_register_pch_pic_device();
if (ret)
- return ret;
+ goto err_eiointc;
/* Register LoongArch DMSINTC interrupt contrroller interface */
- if (cpu_has_msgint)
+ if (cpu_has_msgint) {
ret = kvm_loongarch_register_dmsintc_device();
+ if (ret)
+ goto err_pch_pic;
+ }
+
+ return 0;
+
+err_pch_pic:
+ kvm_loongarch_unregister_pch_pic_device();
+err_eiointc:
+ kvm_loongarch_unregister_eiointc_device();
+err_ipi:
+ kvm_loongarch_unregister_ipi_device();
+err_env:
+ kvm_unregister_perf_callbacks();
+ kfree(kvm_loongarch_ops);
+ kvm_loongarch_ops = NULL;
+ free_percpu(vmcs);
+ vmcs = NULL;
return ret;
}
static void kvm_loongarch_env_exit(void)
{
+ if (cpu_has_msgint)
+ kvm_loongarch_unregister_dmsintc_device();
+
+ kvm_loongarch_unregister_pch_pic_device();
+ kvm_loongarch_unregister_eiointc_device();
+ kvm_loongarch_unregister_ipi_device();
+
if (vmcs)
free_percpu(vmcs);