• Sean Christopherson's avatar
    KVM: Free new dirty bitmap if creating a new memslot fails · c87661f8
    Sean Christopherson authored
    Fix a goof in kvm_prepare_memory_region() where KVM fails to free the
    new memslot's dirty bitmap during a CREATE action if
    kvm_arch_prepare_memory_region() fails.  The logic is supposed to detect
    if the bitmap was allocated and thus needs to be freed, versus if the
    bitmap was inherited from the old memslot and thus needs to be kept.  If
    there is no old memslot, then obviously the bitmap can't have been
    inherited
    
    The bug was exposed by commit 86931ff7 ("KVM: x86/mmu: Do not create
    SPTEs for GFNs that exceed host.MAXPHYADDR"), which made it trivally easy
    for syzkaller to trigger failure during kvm_arch_prepare_memory_region(),
    but the bug can be hit other ways too, e.g. due to -ENOMEM when
    allocating x86's memslot metadata.
    
    The backtrace from kmemleak:
    
      __vmalloc_node_range+0xb40/0xbd0 mm/vmalloc.c:3195
      __vmalloc_node mm/vmalloc.c:3232 [inline]
      __vmalloc+0x49/0x50 mm/vmalloc.c:3246
      __vmalloc_array mm/util.c:671 [inline]
      __vcalloc+0x49/0x70 mm/util.c:694
      kvm_alloc_dirty_bitmap virt/kvm/kvm_main.c:1319
      kvm_prepare_memory_region virt/kvm/kvm_main.c:1551
      kvm_set_memslot+0x1bd/0x690 virt/kvm/kvm_main.c:1782
      __kvm_set_memory_region+0x689/0x750 virt/kvm/kvm_main.c:1949
      kvm_set_memory_region virt/kvm/kvm_main.c:1962
      kvm_vm_ioctl_set_memory_region virt/kvm/kvm_main.c:1974
      kvm_vm_ioctl+0x377/0x13a0 virt/kvm/kvm_main.c:4528
      vfs_ioctl fs/ioctl.c:51
      __do_sys_ioctl fs/ioctl.c:870
      __se_sys_ioctl fs/ioctl.c:856
      __x64_sys_ioctl+0xfc/0x140 fs/ioctl.c:856
      do_syscall_x64 arch/x86/entry/common.c:50
      do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
      entry_SYSCALL_64_after_hwframe+0x44/0xae
    
    And the relevant sequence of KVM events:
    
      ioctl(3, KVM_CREATE_VM, 0)              = 4
      ioctl(4, KVM_SET_USER_MEMORY_REGION, {slot=0,
                                            flags=KVM_MEM_LOG_DIRTY_PAGES,
                                            guest_phys_addr=0x10000000000000,
                                            memory_size=4096,
                                            userspace_addr=0x20fe8000}
           ) = -1 EINVAL (Invalid argument)
    
    Fixes: 244893fa ("KVM: Dynamically allocate "new" memslots from the get-go")
    Cc: stable@vger.kernel.org
    Reported-by: syzbot+8606b8a9cc97a63f1c87@syzkaller.appspotmail.com
    Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
    Message-Id: <20220518003842.1341782-1-seanjc@google.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    c87661f8
kvm_main.c 147 KB