KVM: arm64: Tentative fixes for page-table lifetime issues
Will Deacon
maintainercover KVM: arm64: Tentative fixes for page-table lifetime issues
Hi all,
Sashiko highlighted a couple of potential page-table lifetime issues in the upstream code while it was reviewing the pKVM protected memory series. They make sense to me so I've had a crack at fixing them and writing a better description of the problem in the commit message.
For the second issue, I've tested it by forcing the notifier registration to fail and then watching the SecPageTables line in /proc/meminfo after attempting to create VMs.
Cheers,
Will
--->8
Will Deacon (2):
KVM: arm64: Don't leave mmu->pgt dangling on kvm_init_stage2_mmu()
error
KVM: arm64: Destroy stage-2 page-table in kvm_arch_destroy_vm()
arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/mmu.c | 1 + 2 files changed, 2 insertions(+)
Signature · 1 line
2.53.0.1018.g2bb0e51243-goog
Will Deacon
maintainerPATCH 1/2 KVM: arm64: Don't leave mmu->pgt dangling on kvm_init_stage2_mmu() error
If kvm_init_stage2_mmu() fails to allocate 'mmu->last_vcpu_ran', it destroys the newly allocated stage-2 page-table before returning ENOMEM.
Unfortunately, it also leaves a dangling pointer in 'mmu->pgt' which points at the freed 'kvm_pgtable' structure. This is likely to confuse the kvm_vcpu_init_nested() failure path which can double-free the structure if it finds it via kvm_free_stage2_pgd().
Ensure that the dangling 'mmu->pgt' pointer is cleared when returning an error from kvm_init_stage2_mmu().
--- arch/arm64/kvm/mmu.c | 1 + 1 file changed, 1 insertion(+)
arch/arm64/kvm/mmu.c +1 -0
@@ -1013,6 +1013,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t out_destroy_pgtable:kvm_stage2_destroy (pgt); + mmu->pgt =NULL ; out_free_pgtable:kfree (pgt);return err;
Signature · 1 line
2.53.0.1018.g2bb0e51243-goog
Will Deacon
maintainerPATCH 2/2 KVM: arm64: Destroy stage-2 page-table in kvm_arch_destroy_vm()
In reply to Will Deaconkvm_arch_destroy_vm() can be called on the kvm_create_vm() error path after we have failed to register the MMU notifiers for the new VM. In this case, we cannot rely on the MMU ->release() notifier to call kvm_arch_flush_shadow_all() and so the stage-2 page-table allocated in kvm_arch_init_vm() will be leaked.
Explicitly destroy the stage-2 page-table in kvm_arch_destroy_vm(), so that we clean up after kvm_arch_destroy_vm() without relying on the MMU notifiers.
--- arch/arm64/kvm/arm.c | 1 + 1 file changed, 1 insertion(+)
arch/arm64/kvm/arm.c +1 -0
@@ -301,6 +301,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)if (is_protected_kvm_enabled ())pkvm_destroy_hyp_vm (kvm); +kvm_uninit_stage2_mmu (kvm);kvm_destroy_mpidr_data (kvm);kfree (kvm->arch.sysreg_masks);
Signature · 1 line
2.53.0.1018.g2bb0e51243-goog
Quoted 10 lines · Will Deacon
Sashiko highlighted a couple of potential page-table lifetime issues in the upstream code while it was reviewing the pKVM protected memory series. They make sense to me so I've had a crack at fixing them and writing a better description of the problem in the commit message.
For the second issue, I've tested it by forcing the notifier registration to fail and then watching the SecPageTables line in
/proc/meminfoafter attempting to create VMs.[...]
Applied to next, thanks!
[1/2] KVM: arm64: Don't leave mmu->pgt dangling on kvm_init_stage2_mmu() error
commit: 2fc0f3e2b9a9f397554ffe86e8f6eb0e2507ec6e
[2/2] KVM: arm64: Destroy stage-2 page-table in kvm_arch_destroy_vm()
commit: a3ca3bfd01b7ee9f54ed85718a6d553cdd87050eCheers,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.