KVM: arm64: Fix nested S2 MMU structures reallocation
Marc Zyngier
maintainerPATCH 1/1 KVM: arm64: Fix nested S2 MMU structures reallocation
For each vcpu that userspace creates, we allocate a number of s2_mmu structures that will eventually contain our shadow S2 page tables.
Since this is a dynamically allocated array, we reallocate the array and initialise the newly allocated elements. Once everything is correctly initialised, we adjust pointer and size in the kvm structure, and move on.
But should that initialisation fail *and* the reallocation triggered a copy to another location, we end-up returning early, with the kvm structure still containing the (now stale) old pointer. Weeee!
Cure it by assigning the pointer early, and use this to perform the initialisation. If everything succeeds, we adjust the size. Otherwise, we just leave the size as it was, no harm done, and the new memory is as good as the ol' one (we hope...).
--- arch/arm64/kvm/nested.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/arm64/kvm/nested.c +5 -4
@@ -93,20 +93,22 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)if (!tmp)return -ENOMEM ; +swap (kvm->arch.nested_mmus, tmp); +/* * If we went through a realocation, adjust the MMU back-pointers in * the previously initialised kvm_pgtable structures. */ if (kvm->arch.nested_mmus != tmp)for (int i =0 ; i < kvm->arch.nested_mmus_size; i++) - tmp[i].pgt->mmu = &tmp[i]; + kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++) - ret =init_nested_s2_mmu (kvm, &tmp[i]); + ret =init_nested_s2_mmu (kvm, &kvm->arch.nested_mmus[i]);if (ret) {for (int i = kvm->arch.nested_mmus_size; i < num_mmus; i++) -kvm_free_stage2_pgd (&tmp[i]); +kvm_free_stage2_pgd (&kvm->arch.nested_mmus[i]);free_page ((unsigned long )vcpu->arch.ctxt.vncr_array); vcpu->arch.ctxt.vncr_array =NULL ;
@@ -115,7 +117,6 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu) } kvm->arch.nested_mmus_size = num_mmus; - kvm->arch.nested_mmus = tmp;return 0 ; }
Signature · 1 line
2.39.2
Quoted 14 lines · Marc Zyngier
For each vcpu that userspace creates, we allocate a number of
s2_mmustructures that will eventually contain our shadow S2 page tables.Since this is a dynamically allocated array, we reallocate the array and initialise the newly allocated elements. Once everything is correctly initialised, we adjust pointer and size in the kvm structure, and move on.
But should that initialisation fail *and* the reallocation triggered a copy to another location, we end-up returning early, with the kvm structure still containing the (now stale) old pointer. Weeee!
Quoted 8 lines
Cure it by assigning the pointer early, and use this to perform the initialisation. If everything succeeds, we adjust the size. Otherwise, we just leave the size as it was, no harm done, and the new memory is as good as the ol' one (we hope...).
Fixes 4f128f8e1aaac ("KVM: arm64: nv: Support multiple nested Stage-2 mmu structures")Reported-by Alexander Potapenko <[email protected]>Signed-off-by Marc Zyngier <[email protected]>
Quoted 10 lines · Marc Zyngier
For each vcpu that userspace creates, we allocate a number of
s2_mmustructures that will eventually contain our shadow S2 page tables.Since this is a dynamically allocated array, we reallocate the array and initialise the newly allocated elements. Once everything is correctly initialised, we adjust pointer and size in the kvm structure, and move on.
[...]
Applied to fixes, thanks!
[1/1] KVM: arm64: Fix nested S2 MMU structures reallocation
commit: 5417a2e9b130a78bf48cb4cf92630efcee5ccf38
Cheers,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.