mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
KVM: arm64: Fix __pkvm_init_vm error path
In the unlikely case where insert_vm_table_entry fails, __pkvm_init_vm
release the memory donated by the host for the PGD, but as the stage-2
is still set-up the hypervisor keeps a refcount on those pages,
effectively leaking the references.
Fix the rollback with the newly added kvm_guest_destroy_stage2().
Fixes: 256b4668cd ("KVM: arm64: Introduce separate hypercalls for pKVM VM reservation and initialization")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Link: https://patch.msgid.link/20260521143626.1005660-3-vdonnefort@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
6835fbed39
commit
20d2753295
|
|
@ -56,6 +56,7 @@ int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot p
|
|||
int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id);
|
||||
int kvm_host_prepare_stage2(void *pgt_pool_base);
|
||||
int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd);
|
||||
void kvm_guest_destroy_stage2(struct pkvm_hyp_vm *vm);
|
||||
void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
|
||||
|
||||
int hyp_pin_shared_mem(void *from, void *to);
|
||||
|
|
|
|||
|
|
@ -290,16 +290,21 @@ int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kvm_guest_destroy_stage2(struct pkvm_hyp_vm *vm)
|
||||
{
|
||||
guest_lock_component(vm);
|
||||
kvm_pgtable_stage2_destroy(&vm->pgt);
|
||||
vm->kvm.arch.mmu.pgd_phys = 0ULL;
|
||||
guest_unlock_component(vm);
|
||||
}
|
||||
|
||||
void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
|
||||
{
|
||||
struct hyp_page *page;
|
||||
void *addr;
|
||||
|
||||
/* Dump all pgtable pages in the hyp_pool */
|
||||
guest_lock_component(vm);
|
||||
kvm_pgtable_stage2_destroy(&vm->pgt);
|
||||
vm->kvm.arch.mmu.pgd_phys = 0ULL;
|
||||
guest_unlock_component(vm);
|
||||
kvm_guest_destroy_stage2(vm);
|
||||
|
||||
/* Drain the hyp_pool into the memcache */
|
||||
addr = hyp_alloc_pages(&vm->pool, 0);
|
||||
|
|
|
|||
|
|
@ -839,10 +839,12 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
|
|||
/* Must be called last since this publishes the VM. */
|
||||
ret = insert_vm_table_entry(handle, hyp_vm);
|
||||
if (ret)
|
||||
goto err_remove_mappings;
|
||||
goto err_destroy_stage2;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_stage2:
|
||||
kvm_guest_destroy_stage2(hyp_vm);
|
||||
err_remove_mappings:
|
||||
unmap_donated_memory(hyp_vm, vm_size);
|
||||
unmap_donated_memory(pgd, pgd_size);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user