git: d4c05edd410e - main - vmm: Add privilege checks to vmmctl operations

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 19 Feb 2026 17:16:29 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=d4c05edd410e7925875c844c0642929410f22053

commit d4c05edd410e7925875c844c0642929410f22053
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-02-19 14:38:29 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-02-19 17:16:15 +0000

    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
---
 sys/dev/vmm/vmm_dev.c | 21 +++++++++++++++++++++
 sys/sys/priv.h        |  4 +++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index 0df21402683d..5d7802f929ae 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -898,6 +898,7 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred)
 {
 	struct cdev *cdev;
 	struct vmmdev_softc *sc;
+	int error;
 
 	sx_xlock(&vmmdev_mtx);
 	sc = vmmdev_lookup(name, cred);
@@ -906,6 +907,16 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred)
 		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
 	 * is scheduled for destruction.
@@ -992,6 +1003,16 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred)
 		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)) {
 		sx_xunlock(&vmmdev_mtx);
 		return (ENOMEM);
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
index 1ad6a4882ffc..e302d9487e64 100644
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -539,11 +539,13 @@
  * vmm privileges.
  */
 #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.
  */
-#define	_PRIV_HIGHEST		711
+#define	_PRIV_HIGHEST		713
 
 /*
  * Validate that a named privilege is known by the privilege system.  Invalid