Page MenuHomeFreeBSD

D31225.id92448.diff
No OneTemporary

D31225.id92448.diff

diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -40,6 +40,7 @@
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
+#include <sys/mount.h>
#include <sys/conf.h>
#include <sys/sysctl.h>
#include <sys/libkern.h>
@@ -91,6 +92,7 @@
static unsigned pr_allow_flag;
static struct mtx vmmdev_mtx;
+static unsigned vmmdev_prison_slot;
static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev");
@@ -99,6 +101,7 @@
static int vmm_priv_check(struct ucred *ucred);
static int devmem_create_cdev(const char *vmname, int id, char *devmem);
static void devmem_destroy(void *arg);
+static int vmm_destroy(struct vmmdev_softc *sc);
static int
vmm_priv_check(struct ucred *ucred)
@@ -997,31 +1000,13 @@
}
static int
-sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
+vmm_destroy(struct vmmdev_softc *sc)
{
struct devmem_softc *dsc;
- struct vmmdev_softc *sc;
struct cdev *cdev;
- char *buf;
- int error, buflen;
-
- error = vmm_priv_check(req->td->td_ucred);
- if (error)
- return (error);
-
- buflen = VM_MAX_NAMELEN + 1;
- buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO);
- strlcpy(buf, "beavis", buflen);
- error = sysctl_handle_string(oidp, buf, buflen, req);
- if (error != 0 || req->newptr == NULL)
- goto out;
- mtx_lock(&vmmdev_mtx);
- sc = vmmdev_lookup(buf);
if (sc == NULL || sc->cdev == NULL) {
- mtx_unlock(&vmmdev_mtx);
- error = EINVAL;
- goto out;
+ return (EINVAL);
}
/*
@@ -1033,7 +1018,6 @@
*/
cdev = sc->cdev;
sc->cdev = NULL;
- mtx_unlock(&vmmdev_mtx);
/*
* Schedule all cdevs to be destroyed:
@@ -1051,8 +1035,34 @@
destroy_dev_sched_cb(dsc->cdev, devmem_destroy, dsc);
}
destroy_dev_sched_cb(cdev, vmmdev_destroy, sc);
- error = 0;
+ return (0);
+}
+
+static int
+sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
+{
+ struct vmmdev_softc *sc;
+ char *buf;
+ int error, buflen;
+
+ error = vmm_priv_check(req->td->td_ucred);
+ if (error)
+ return (error);
+
+ buflen = VM_MAX_NAMELEN + 1;
+ buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO);
+ strlcpy(buf, "beavis", buflen);
+ error = sysctl_handle_string(oidp, buf, buflen, req);
+ if (error != 0 || req->newptr == NULL)
+ goto out;
+
+ mtx_lock(&vmmdev_mtx);
+
+ sc = vmmdev_lookup(buf);
+ error = vmm_destroy(sc);
+
+ mtx_unlock(&vmmdev_mtx);
out:
free(buf, M_VMMDEV);
return (error);
@@ -1147,12 +1157,59 @@
NULL, 0, sysctl_vmm_create, "A",
NULL);
+static void
+vmmdev_prison_cleanup(struct prison *pr)
+{
+ struct vmmdev_softc *sc;
+
+ mtx_lock(&vmmdev_mtx);
+
+ SLIST_FOREACH(sc, &head, link) {
+ if (sc->ucred->cr_prison == pr)
+ vmm_destroy(sc);
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+}
+
+static int
+vmmdev_prison_remove(void *obj, void *data __unused)
+{
+ struct prison *pr = obj;
+
+ vmmdev_prison_cleanup(pr);
+ return (0);
+}
+
+static int
+vmmdev_prison_set(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ bool vmm_disabled = false;
+
+ if (vfs_flagopt(opts, "allow.novmm", NULL, 0))
+ vmm_disabled = true;
+
+ if (vmm_disabled)
+ vmmdev_prison_cleanup(pr);
+
+ return (0);
+}
+
void
vmmdev_init(void)
{
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_SET] = vmmdev_prison_set,
+ [PR_METHOD_REMOVE] = vmmdev_prison_remove,
+ };
+
mtx_init(&vmmdev_mtx, "vmm device mutex", NULL, MTX_DEF);
pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
"Allow use of vmm in a jail.");
+
+ vmmdev_prison_slot = osd_jail_register(NULL, methods);
}
int
@@ -1160,10 +1217,12 @@
{
int error;
- if (SLIST_EMPTY(&head))
+ if (SLIST_EMPTY(&head)) {
+ osd_jail_deregister(vmmdev_prison_slot);
error = 0;
- else
+ } else {
error = EBUSY;
+ }
return (error);
}
diff --git a/tests/sys/vmm/Makefile b/tests/sys/vmm/Makefile
--- a/tests/sys/vmm/Makefile
+++ b/tests/sys/vmm/Makefile
@@ -4,7 +4,8 @@
BINDIR= ${TESTSDIR}
-ATF_TESTS_SH+= vmm_cred_jail
+ATF_TESTS_SH+= vmm_cred_jail \
+ vmm_remove_jail
${PACKAGE}FILES+= utils.subr
diff --git a/tests/sys/vmm/vmm_remove_jail.sh b/tests/sys/vmm/vmm_remove_jail.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/vmm/vmm_remove_jail.sh
@@ -0,0 +1,81 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+#
+# Copyright (c) 2021 The FreeBSD Foundation
+#
+# This software was developed by Cyril Zhang under sponsorship from
+# the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+. $(atf_get_srcdir)/utils.subr
+
+atf_test_case vmm_remove_jail cleanup
+vmm_remove_jail_head()
+{
+ atf_set "descr" "Tests deleting a jail that has VM objects"
+ atf_set "require.user" "root"
+}
+vmm_remove_jail_body()
+{
+ if ! kldstat -qn vmm; then
+ atf_skip "vmm is not loaded"
+ fi
+ jail -c name=myjail allow.vmm persist
+ jexec myjail bhyvectl --vm=testvm --create
+ jail -r myjail
+ atf_check -s exit:1 -e ignore ls /dev/vmm
+}
+vmm_remove_jail_cleanup()
+{
+ bhyvectl --vm=testvm --destroy
+ vmm_cleanup
+}
+
+atf_test_case vmm_unenable_jail cleanup
+vmm_unenable_jail_head()
+{
+ atf_set "descr" "Tests allow.vmm=false on a jail that has VM objects"
+ atf_set "require.user" "root"
+}
+vmm_unenable_jail_body()
+{
+ if ! kldstat -qn vmm; then
+ atf_skip "vmm is not loaded"
+ fi
+ vmm_mkjail myjail
+ jexec myjail bhyvectl --vm=testvm --create
+ jail -m name=myjail allow.vmm=false
+ atf_check -s exit:1 -e ignore ls /dev/vmm
+}
+vmm_unenable_jail_cleanup()
+{
+ bhyvectl --vm=testvm --destroy
+ vmm_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case vmm_remove_jail
+ atf_add_test_case vmm_unenable_jail
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 7, 12:01 PM (9 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36170213
Default Alt Text
D31225.id92448.diff (6 KB)

Event Timeline