HV:refine 'create_vm()' to avoid potential crash and memory leak

hypervisor will crash if user try to call hypercall
  HC_CREATE_VM in infinite style.

  actually, the number of VMs hypervisor can support
  depends on the bit width of 'vmid_bitmap'.should
  return error in case of overflow.

  other cleanup for this function to avoid memory leak
  in case of failure.

Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yonghua Huang 2018-07-26 00:08:28 +08:00 committed by lijinxia
parent 53a5941b99
commit 45d6f72b51

View File

@ -99,14 +99,21 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
if (vm->hw.vcpu_array == NULL) { if (vm->hw.vcpu_array == NULL) {
pr_err("%s, vcpu_array allocation failed\n", __func__); pr_err("%s, vcpu_array allocation failed\n", __func__);
status = -ENOMEM; status = -ENOMEM;
goto err1; goto err;
} }
for (id = 0U; id < (size_t)(sizeof(long) * 8U); id++) { for (id = 0U; id < (size_t)(sizeof(vmid_bitmap) * 8U); id++) {
if (!bitmap_test_and_set(id, &vmid_bitmap)) { if (!bitmap_test_and_set(id, &vmid_bitmap)) {
break; break;
} }
} }
if (id >= (size_t)(sizeof(vmid_bitmap) * 8U)) {
pr_err("%s, no more VMs can be supported\n", __func__);
status = -EINVAL;
goto err;
}
vm->attr.id = id; vm->attr.id = id;
vm->attr.boot_idx = id; vm->attr.boot_idx = id;
@ -120,7 +127,8 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
if ((vm->arch_vm.nworld_eptp == NULL) || if ((vm->arch_vm.nworld_eptp == NULL) ||
(vm->arch_vm.m2p == NULL)) { (vm->arch_vm.m2p == NULL)) {
pr_fatal("%s, alloc memory for EPTP failed\n", __func__); pr_fatal("%s, alloc memory for EPTP failed\n", __func__);
return -ENOMEM; status = -ENOMEM;
goto err;
} }
/* Only for SOS: Configure VM software information */ /* Only for SOS: Configure VM software information */
@ -128,12 +136,12 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
if (is_vm0(vm)) { if (is_vm0(vm)) {
status = prepare_vm0_memmap_and_e820(vm); status = prepare_vm0_memmap_and_e820(vm);
if (status != 0) { if (status != 0) {
goto err2; goto err;
} }
#ifndef CONFIG_EFI_STUB #ifndef CONFIG_EFI_STUB
status = init_vm0_boot_info(vm); status = init_vm0_boot_info(vm);
if (status != 0) { if (status != 0) {
goto err2; goto err;
} }
#endif #endif
} else { } else {
@ -175,7 +183,7 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
vm->arch_vm.virt_ioapic = vioapic_init(vm); vm->arch_vm.virt_ioapic = vioapic_init(vm);
if (vm->arch_vm.virt_ioapic == NULL) { if (vm->arch_vm.virt_ioapic == NULL) {
status = -ENODEV; status = -ENODEV;
goto err3; goto err;
} }
/* Populate return VM handle */ /* Populate return VM handle */
@ -184,20 +192,34 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
status = set_vcpuid_entries(vm); status = set_vcpuid_entries(vm);
if (status != 0) { if (status != 0) {
goto err4; goto err;
} }
vm->state = VM_CREATED; vm->state = VM_CREATED;
return 0; return 0;
err4: err:
if (vm->arch_vm.virt_ioapic != NULL) {
vioapic_cleanup(vm->arch_vm.virt_ioapic); vioapic_cleanup(vm->arch_vm.virt_ioapic);
err3: }
if (vm->vpic != NULL) {
vpic_cleanup(vm); vpic_cleanup(vm);
err2: }
if (vm->arch_vm.m2p != NULL) {
free(vm->arch_vm.m2p);
}
if (vm->arch_vm.nworld_eptp != NULL) {
free(vm->arch_vm.nworld_eptp);
}
if (vm->hw.vcpu_array != NULL) {
free(vm->hw.vcpu_array); free(vm->hw.vcpu_array);
err1: }
free(vm); free(vm);
return status; return status;
} }