When installing a KVM-internal memslot, delete the non-SMM memslot if creating the SMM memslot fails. Leaving the non-SMM memslot in-place makes it impossible for userspace to recover (not that any VMM tries), as subsequent tries to install the internal memslot will fail with -EEXIST. Fixes: 9da0e4d5ac96 ("KVM: x86: work on all available address spaces") Signed-off-by: Sean Christopherson --- arch/x86/kvm/x86.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 489631686ba6..326f8a9a5d18 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10006,6 +10006,19 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) return ret; } +static int x86_set_internal_memslot(struct kvm *kvm, int id, int as_id, + gpa_t gpa, unsigned long hva, u32 size) +{ + struct kvm_userspace_memory_region2 m; + + m.slot = id | (as_id << 16); + m.flags = 0; + m.guest_phys_addr = gpa; + m.userspace_addr = hva; + m.memory_size = size; + return kvm_set_internal_memslot(kvm, &m); +} + /** * __x86_set_memory_region: Setup KVM internal memory slot * @@ -10062,16 +10075,17 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, } for (i = 0; i < kvm_arch_nr_memslot_as_ids(kvm); i++) { - struct kvm_userspace_memory_region2 m; + r = x86_set_internal_memslot(kvm, id, i, gpa, hva, size); + if (!r) + continue; - m.slot = id | (i << 16); - m.flags = 0; - m.guest_phys_addr = gpa; - m.userspace_addr = hva; - m.memory_size = size; - r = kvm_set_internal_memslot(kvm, &m); - if (r < 0) - return ERR_PTR_USR(r); + if (size) { + for (i--; i >= 0; i--) + x86_set_internal_memslot(kvm, id, i, gpa, 0, 0); + + vm_munmap(hva, size); + } + return ERR_PTR_USR(r); } return (void __user *)hva; -- 2.56.0.385.gac671c819a-goog