diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c --- a/sys/dev/vmm/vmm_dev.c +++ b/sys/dev/vmm/vmm_dev.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,10 @@ SYSCTL_UINT(_hw_vmm, OID_AUTO, maxcpu, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &vm_maxcpu, 0, "Maximum number of vCPUs"); +u_int vm_maxvmms; +SYSCTL_UINT(_hw_vmm, OID_AUTO, maxvmms, CTLFLAG_RW, + &vm_maxvmms, 0, "Maximum number of VMM instances per user"); + static void devmem_destroy(void *arg); static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem); @@ -898,8 +903,10 @@ if (sc->vm != NULL) vm_destroy(sc->vm); - if (sc->ucred != NULL) + if (sc->ucred != NULL) { + chgvmmcnt(sc->ucred->cr_ruidinfo, -1, 0); crfree(sc->ucred); + } sx_xlock(&vmmdev_mtx); SLIST_REMOVE(&head, sc, vmmdev_softc, link); @@ -999,6 +1006,11 @@ return (EEXIST); } + if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) { + sx_xunlock(&vmmdev_mtx); + return (ENOMEM); + } + error = vm_create(name, &vm); if (error != 0) { sx_xunlock(&vmmdev_mtx); @@ -1172,7 +1184,7 @@ } if (vm_maxcpu == 0) vm_maxcpu = 1; - + vm_maxvmms = MAX(mp_ncpus * 2, 1024); error = vmm_modinit(); if (error == 0) vmm_initialized = true; diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -895,6 +895,9 @@ case RLIMIT_PIPEBUF: *res = ui->ui_pipecnt; break; + case RLIMIT_VMM: + *res = ui->ui_vmmcnt; + break; default: error = EINVAL; break; @@ -1643,6 +1646,9 @@ if (uip->ui_inotifywatchcnt != 0) printf("freeing uidinfo: uid = %d, inotifywatchcnt = %ld\n", uip->ui_uid, uip->ui_inotifywatchcnt); + if (uip->ui_vmmcnt != 0) + printf("freeing vmmcnt: uid = %d, vmmcnt = %ld\n", + uip->ui_uid, uip->ui_vmmcnt); free(uip, M_UIDINFO); } @@ -1763,6 +1769,13 @@ "inotifywatchcnt")); } +int +chgvmmcnt(struct uidinfo *uip, int diff, rlim_t max) +{ + + return (chglimit(uip, &uip->ui_vmmcnt, diff, max, "proccnt")); +} + static int sysctl_kern_proc_rlimit_usage(SYSCTL_HANDLER_ARGS) { diff --git a/sys/sys/resource.h b/sys/sys/resource.h --- a/sys/sys/resource.h +++ b/sys/sys/resource.h @@ -115,8 +115,9 @@ #define RLIMIT_KQUEUES 13 /* kqueues allocated */ #define RLIMIT_UMTXP 14 /* process-shared umtx */ #define RLIMIT_PIPEBUF 15 /* pipes/fifos buffers */ +#define RLIMIT_VMM 16 /* virtual machines */ -#define RLIM_NLIMITS 16 /* number of resource limits */ +#define RLIM_NLIMITS 17 /* number of resource limits */ #define RLIM_INFINITY ((rlim_t)(((__uint64_t)1 << 63) - 1)) #define RLIM_SAVED_MAX RLIM_INFINITY @@ -144,6 +145,7 @@ "kqueues", "umtx", "pipebuf", + "vmm", }; #endif diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -124,6 +124,7 @@ long ui_pipecnt; /* (b) consumption of pipe buffers */ long ui_inotifycnt; /* (b) number of inotify descriptors */ long ui_inotifywatchcnt; /* (b) number of inotify watches */ + long ui_vmmcnt; /* (b) number of vmm instances */ uid_t ui_uid; /* (a) uid */ u_int ui_ref; /* (b) reference count */ #ifdef RACCT @@ -148,6 +149,7 @@ int chgpipecnt(struct uidinfo *uip, int diff, rlim_t max); int chginotifycnt(struct uidinfo *uip, int diff, rlim_t maxval); int chginotifywatchcnt(struct uidinfo *uip, int diff, rlim_t maxval); +int chgvmmcnt(struct uidinfo *uip, int diff, rlim_t max); int kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, struct rlimit *limp); struct plimit