aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2026-04-01 09:25:27 +0000
committerMark Johnston <markj@FreeBSD.org>2026-04-01 11:16:14 +0000
commitf3c772361f3b6213ec7ae7de993b6953357c7b48 (patch)
tree4d173d2693f0a48ca644baa19d24bd5040c4793b
parentc6a1c1260f02e44b7f44b1e3735ce5dbd785544d (diff)
vmm: Restore the ability to create VMs as root in a jail
The new PRIV_VMM_CREATE and DESTROY permissions should be allowed by jails, so need to be added to the list in prison_priv_check(). Then, modify vmmdev_create() to verify that the jail was created with the allow.vmm flag. This is already verified when opening /dev/vmmctl, but checking again doesn't hurt and ensures that one can't pass the allow.vmm policy by passing a vmmctl fd along a unix domain socket from outside the jail. Rename vmm_priv_check() to vmm_jail_priv_check() to make the function's purpose more clear. Reported by: novel Reviewed by: bnovkov Fixes: d4c05edd410e ("vmm: Add privilege checks to vmmctl operations") Differential Revision: https://reviews.freebsd.org/D56119
-rw-r--r--sys/dev/vmm/vmm_dev.c16
-rw-r--r--sys/kern/kern_jail.c8
2 files changed, 19 insertions, 5 deletions
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index ed8e5b2e0777..a2775023838a 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -114,7 +114,7 @@ static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem);
static void vmmdev_destroy(struct vmmdev_softc *sc);
static int
-vmm_priv_check(struct ucred *ucred)
+vmm_jail_priv_check(struct ucred *ucred)
{
if (jailed(ucred) &&
(ucred->cr_prison->pr_allow & pr_allow_vmm_flag) == 0)
@@ -371,7 +371,7 @@ vmmdev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
* A jail without vmm access shouldn't be able to access vmm device
* files at all, but check here just to be thorough.
*/
- error = vmm_priv_check(td->td_ucred);
+ error = vmm_jail_priv_check(td->td_ucred);
if (error != 0)
return (error);
@@ -940,7 +940,7 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
char *buf;
int error, buflen;
- error = vmm_priv_check(req->td->td_ucred);
+ error = vmm_jail_priv_check(req->td->td_ucred);
if (error)
return (error);
@@ -1016,6 +1016,12 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred)
"An unprivileged user must run VMs in monitor mode"));
}
+ if ((error = vmm_jail_priv_check(cred)) != 0) {
+ sx_xunlock(&vmmdev_mtx);
+ return (EXTERROR(error,
+ "VMs cannot be created in the current jail"));
+ }
+
if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) {
sx_xunlock(&vmmdev_mtx);
return (ENOMEM);
@@ -1061,7 +1067,7 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
if (!vmm_initialized)
return (ENXIO);
- error = vmm_priv_check(req->td->td_ucred);
+ error = vmm_jail_priv_check(req->td->td_ucred);
if (error != 0)
return (error);
@@ -1126,7 +1132,7 @@ vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
int error;
struct vmmctl_priv *priv;
- error = vmm_priv_check(td->td_ucred);
+ error = vmm_jail_priv_check(td->td_ucred);
if (error != 0)
return (error);
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 9f78cb42aeb1..384825b7f8ac 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -4736,6 +4736,14 @@ prison_priv_check(struct ucred *cred, int priv)
else
return (EPERM);
+ case PRIV_VMM_CREATE:
+ case PRIV_VMM_DESTROY:
+ /*
+ * Jailed root can create and destroy VMs; the vmm module
+ * additionally checks for the allow.vmm flag.
+ */
+ return (0);
+
case PRIV_VMM_PPTDEV:
/*
* Allow jailed root to manage passthrough devices. vmm(4) also