Skip to content

Commit 185d903

Browse files
Claudio Imbrendafrankjaa
authored andcommitted
KVM: s390: Fix incorrect usage of mmu_notifier_register()
If mmu_notifier_register() fails, for example because a signal was pending, the mmu_notifier will not be registered. But when the VM gets destroyed, it will get unregistered anyway and that will cause one extra mmdrop(), which will eventually cause the mm of the process to be freed too early, and cause a use-after free. This bug happens rarely, and only when secure guests are involved. The solution is to check the return value of mmu_notifier_register() and return it to the caller (ultimately it will be propagated all the way to userspace). In case of -EINTR, userspace will try again. Fixes: ca2fd06 ("KVM: s390: pv: add mmu_notifier") Signed-off-by: Claudio Imbrenda <[email protected]> Reviewed-by: Christian Borntraeger <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Reviewed-by: Steffen Eiden <[email protected]> Reviewed-by: Christoph Schlameuss <[email protected]> Signed-off-by: Janosch Frank <[email protected]>
1 parent de4da7b commit 185d903

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

arch/s390/kvm/pv.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,17 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
624624
int cc, ret;
625625
u16 dummy;
626626

627+
/* Add the notifier only once. No races because we hold kvm->lock */
628+
if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
629+
/* The notifier will be unregistered when the VM is destroyed */
630+
kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
631+
ret = mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
632+
if (ret) {
633+
kvm->arch.pv.mmu_notifier.ops = NULL;
634+
return ret;
635+
}
636+
}
637+
627638
ret = kvm_s390_pv_alloc_vm(kvm);
628639
if (ret)
629640
return ret;
@@ -659,11 +670,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
659670
return -EIO;
660671
}
661672
kvm->arch.gmap->guest_handle = uvcb.guest_handle;
662-
/* Add the notifier only once. No races because we hold kvm->lock */
663-
if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
664-
kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
665-
mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
666-
}
667673
return 0;
668674
}
669675

0 commit comments

Comments
 (0)