git: 4008758105a6 - main - vmm: Validate credentials when opening a vmmdev
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 01 Sep 2024 14:09:42 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=4008758105a6da9eaa0b96b81dfb3042a33259be
commit 4008758105a6da9eaa0b96b81dfb3042a33259be
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-09-01 14:00:32 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-09-01 14:03:16 +0000
vmm: Validate credentials when opening a vmmdev
Rather than performing privilege checks after a specific VM's device
file is opened, do it once at the time the device file is opened. This
means that one can continue to access a VM via its device fd after
attaching to a jail which does not have vmm enabled, but this seems like
a reasonable semantic to have anyway.
Reviewed by: jhb
Differential Revision: https://reviews.freebsd.org/D46486
---
sys/dev/vmm/vmm_dev.c | 39 +++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index f43429de4d4c..b4ae2997006f 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -186,10 +186,6 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
void *hpa, *cookie;
struct vmmdev_softc *sc;
- error = vmm_priv_check(curthread->td_ucred);
- if (error)
- return (error);
-
sc = vmmdev_lookup2(cdev);
if (sc == NULL)
return (ENXIO);
@@ -327,6 +323,32 @@ vm_set_register_set(struct vcpu *vcpu, unsigned int count, int *regnum,
return (error);
}
+static int
+vmmdev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+ struct vmmdev_softc *sc;
+ int error;
+
+ sc = vmmdev_lookup2(dev);
+ KASSERT(sc != NULL, ("%s: device not found", __func__));
+
+ /*
+ * A user can only access VMs that they themselves have created.
+ */
+ if (td->td_ucred != sc->ucred)
+ return (EPERM);
+
+ /*
+ * 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);
+ if (error != 0)
+ return (error);
+
+ return (0);
+}
+
static const struct vmmdev_ioctl vmmdev_ioctls[] = {
VMMDEV_IOCTL(VM_GET_REGISTER, VMMDEV_IOCTL_LOCK_ONE_VCPU),
VMMDEV_IOCTL(VM_SET_REGISTER, VMMDEV_IOCTL_LOCK_ONE_VCPU),
@@ -375,10 +397,6 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
const struct vmmdev_ioctl *ioctl;
int error, vcpuid;
- error = vmm_priv_check(td->td_ucred);
- if (error)
- return (error);
-
sc = vmmdev_lookup2(cdev);
if (sc == NULL)
return (ENXIO);
@@ -681,10 +699,6 @@ vmmdev_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t mapsize,
int error, found, segid;
bool sysmem;
- error = vmm_priv_check(curthread->td_ucred);
- if (error)
- return (error);
-
first = *offset;
last = first + mapsize;
if ((nprot & PROT_EXEC) || first < 0 || first >= last)
@@ -833,6 +847,7 @@ SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy,
static struct cdevsw vmmdevsw = {
.d_name = "vmmdev",
.d_version = D_VERSION,
+ .d_open = vmmdev_open,
.d_ioctl = vmmdev_ioctl,
.d_mmap_single = vmmdev_mmap_single,
.d_read = vmmdev_rw,