From 8e3b4c1f83f1d72192462b7c738fa33755b4eea7 Mon Sep 17 00:00:00 2001 From: dv Date: Mon, 13 Sep 2021 22:16:27 +0000 Subject: [PATCH] vmm(4): add limit to number of vcpus After fixing previous syzbot issues related to lock contention, the reproducer code managed to hit an issue where it can exhaust kernel memory by allocating vcpus. Since each vcpu (regardless if it's SVM or VMX-capable) requires wiring some number of pages of memory, it was possible to starve other parts of the kernel. This change limits the total number of vcpus to 512, a conservative number given vmm(4) only supports single vcpu guests at the moment. ok mlarkin@ --- sys/arch/amd64/amd64/vmm.c | 18 +++++++++++++++--- sys/arch/amd64/include/vmmvar.h | 3 ++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index 1ee57d10d15..3ddd41a05d5 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.292 2021/09/05 16:36:34 dv Exp $ */ +/* $OpenBSD: vmm.c,v 1.293 2021/09/13 22:16:27 dv Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -99,6 +99,9 @@ struct vmm_softc { int mode; + size_t vcpu_ct; + size_t vcpu_max; + struct rwlock vm_lock; size_t vm_ct; /* number of in-memory VMs */ size_t vm_idx; /* next unique VM index */ @@ -368,6 +371,7 @@ vmm_attach(struct device *parent, struct device *self, void *aux) sc->nr_svm_cpus = 0; sc->nr_rvi_cpus = 0; sc->nr_ept_cpus = 0; + sc->vcpu_ct = 0; sc->vm_ct = 0; sc->vm_idx = 0; @@ -1498,6 +1502,15 @@ vm_create(struct vm_create_params *vcp, struct proc *p) if (vcp->vcp_ncpus != 1) return (EINVAL); + rw_enter_write(&vmm_softc->vm_lock); + if (vmm_softc->vcpu_ct + vcp->vcp_ncpus > VMM_MAX_VCPUS) { + DPRINTF("%s: maximum vcpus (%lu) reached\n", __func__, + vmm_softc->vcpu_max); + rw_exit_write(&vmm_softc->vm_lock); + return (ENOMEM); + } + vmm_softc->vcpu_ct += vcp->vcp_ncpus; + vm = pool_get(&vm_pool, PR_WAITOK | PR_ZERO); SLIST_INIT(&vm->vm_vcpu_list); rw_init(&vm->vm_vcpu_lock, "vcpu_list"); @@ -1509,8 +1522,6 @@ vm_create(struct vm_create_params *vcp, struct proc *p) vm->vm_memory_size = memsize; strncpy(vm->vm_name, vcp->vcp_name, VMM_MAX_NAME_LEN - 1); - rw_enter_write(&vmm_softc->vm_lock); - if (vm_impl_init(vm, p)) { printf("failed to init arch-specific features for vm %p\n", vm); vm_teardown(vm); @@ -3784,6 +3795,7 @@ vm_teardown(struct vm *vm) SLIST_REMOVE(&vm->vm_vcpu_list, vcpu, vcpu, vc_vcpu_link); vcpu_deinit(vcpu); pool_put(&vcpu_pool, vcpu); + vmm_softc->vcpu_ct--; } vm_impl_deinit(vm); diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index 843df0ffad4..94bb172832d 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmmvar.h,v 1.73 2021/08/31 17:40:59 dv Exp $ */ +/* $OpenBSD: vmmvar.h,v 1.74 2021/09/13 22:16:27 dv Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -29,6 +29,7 @@ #define VMM_MAX_PATH_CDROM 128 #define VMM_MAX_NAME_LEN 64 #define VMM_MAX_KERNEL_PATH 128 +#define VMM_MAX_VCPUS 512 #define VMM_MAX_VCPUS_PER_VM 64 #define VMM_MAX_VM_MEM_SIZE 32768 #define VMM_MAX_NICS_PER_VM 4 -- 2.20.1