vmm: Add privilege checks to vmmctl operations

In preparation for supporting creation of VMs by unprivileged users, add
some restrictions:
- Disallow creation of non-transient VMs by unprivileged users.  That
  is, if an unprivileged user creates a VM, the VM must be destroyed
  automatically once the last fd referencing it is gone.
- Disallow destroying VMs created by a different user, unless the caller
  has the PRIV_VMM_DESTROY privilege.

Reviewed by:	bnovkov
MFC after:	2 months
Sponsored by:	The FreeBSD Foundation
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D54740
This commit is contained in:
Mark Johnston
2026-02-19 14:38:29 +00:00
parent dcbd1fccdc
commit d4c05edd41
2 changed files with 24 additions and 1 deletions
+21
View File
@@ -898,6 +898,7 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred)
{ {
struct cdev *cdev; struct cdev *cdev;
struct vmmdev_softc *sc; struct vmmdev_softc *sc;
int error;
sx_xlock(&vmmdev_mtx); sx_xlock(&vmmdev_mtx);
sc = vmmdev_lookup(name, cred); sc = vmmdev_lookup(name, cred);
@@ -906,6 +907,16 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred)
return (EINVAL); return (EINVAL);
} }
/*
* Only the creator of a VM or a privileged user can destroy it.
*/
if ((cred->cr_uid != sc->ucred->cr_uid ||
cred->cr_prison != sc->ucred->cr_prison) &&
(error = priv_check_cred(cred, PRIV_VMM_DESTROY)) != 0) {
sx_xunlock(&vmmdev_mtx);
return (error);
}
/* /*
* Setting 'sc->cdev' to NULL is used to indicate that the VM * Setting 'sc->cdev' to NULL is used to indicate that the VM
* is scheduled for destruction. * is scheduled for destruction.
@@ -992,6 +1003,16 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred)
return (EEXIST); return (EEXIST);
} }
/*
* Unprivileged users can only create VMs that will be automatically
* destroyed when the creating descriptor is closed.
*/
if ((flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) == 0 &&
(error = priv_check_cred(cred, PRIV_VMM_CREATE)) != 0) {
sx_xunlock(&vmmdev_mtx);
return (error);
}
if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) { if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) {
sx_xunlock(&vmmdev_mtx); sx_xunlock(&vmmdev_mtx);
return (ENOMEM); return (ENOMEM);
+3 -1
View File
@@ -539,11 +539,13 @@
* vmm privileges. * vmm privileges.
*/ */
#define PRIV_VMM_PPTDEV 710 /* Can manipulate ppt devices. */ #define PRIV_VMM_PPTDEV 710 /* Can manipulate ppt devices. */
#define PRIV_VMM_CREATE 711 /* Can create non-temporal VMs. */
#define PRIV_VMM_DESTROY 712 /* Can destroy other users' VMs. */
/* /*
* Track end of privilege list. * Track end of privilege list.
*/ */
#define _PRIV_HIGHEST 711 #define _PRIV_HIGHEST 713
/* /*
* Validate that a named privilege is known by the privilege system. Invalid * Validate that a named privilege is known by the privilege system. Invalid