diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2024-09-01 14:00:32 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2024-09-01 14:03:16 +0000 |
| commit | 4008758105a6da9eaa0b96b81dfb3042a33259be (patch) | |
| tree | cdc6a17fbc55d3345358c235795451bd8d318bc4 | |
| parent | 133a513ddc9aedf83489373f4af9971347bc6201 (diff) | |
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
| -rw-r--r-- | sys/dev/vmm/vmm_dev.c | 39 |
1 files 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, |
