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:
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user