git: 4a46ece6c6a9 - main - vmm: Fix error handling in vmm_handler()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 09 Jan 2025 14:53:11 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=4a46ece6c6a90f18effbfae7ddef79b41ef43eec
commit 4a46ece6c6a90f18effbfae7ddef79b41ef43eec
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-01-09 14:49:34 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-01-09 14:49:34 +0000
vmm: Fix error handling in vmm_handler()
In commit a97f683fe3c4 I didn't add code to remove the vmmctl device
when vmm.ko is unloaded, so it would persist and prevent vmm.ko from
being re-loaded.
Extend vmmdev_cleanup() to destroy the vmmctl cdev. Also call
vmmdev_cleanup() if vmm_init() fails.
Reviewed by: corvink, andrew
Fixes: a97f683fe3c4 ("vmm: Add a device file interface for creating and destroying VMs")
Differential Revision: https://reviews.freebsd.org/D48269
---
sys/amd64/vmm/vmm.c | 2 ++
sys/arm64/vmm/vmm.c | 11 ++++++++---
sys/dev/vmm/vmm_dev.c | 34 +++++++++++++++++++---------------
sys/riscv/vmm/vmm.c | 11 ++++++++---
4 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index d05d979a531a..aa13d506ac6a 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -467,6 +467,8 @@ vmm_handler(module_t mod, int what, void *arg)
error = vmm_init();
if (error == 0)
vmm_initialized = 1;
+ else
+ (void)vmmdev_cleanup();
} else {
error = ENXIO;
}
diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c
index 808df5e599ac..77c565e37264 100644
--- a/sys/arm64/vmm/vmm.c
+++ b/sys/arm64/vmm/vmm.c
@@ -361,21 +361,26 @@ vmm_handler(module_t mod, int what, void *arg)
switch (what) {
case MOD_LOAD:
- /* TODO: if (vmm_is_hw_supported()) { */
error = vmmdev_init();
if (error != 0)
break;
error = vmm_init();
if (error == 0)
vmm_initialized = true;
+ else
+ (void)vmmdev_cleanup();
break;
case MOD_UNLOAD:
- /* TODO: if (vmm_is_hw_supported()) { */
error = vmmdev_cleanup();
if (error == 0 && vmm_initialized) {
error = vmmops_modcleanup();
- if (error)
+ if (error) {
+ /*
+ * Something bad happened - prevent new
+ * VMs from being created
+ */
vmm_initialized = false;
+ }
}
break;
default:
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index 4ab99f92f72a..27c960c8ef2e 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -979,6 +979,7 @@ vmmctl_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
return (error);
}
+static struct cdev *vmmctl_cdev;
static struct cdevsw vmmctlsw = {
.d_name = "vmmctl",
.d_version = D_VERSION,
@@ -989,31 +990,34 @@ static struct cdevsw vmmctlsw = {
int
vmmdev_init(void)
{
- struct cdev *cdev;
int error;
- error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmctlsw, NULL,
+ sx_xlock(&vmmdev_mtx);
+ error = make_dev_p(MAKEDEV_CHECKNAME, &vmmctl_cdev, &vmmctlsw, NULL,
UID_ROOT, GID_WHEEL, 0600, "vmmctl");
- if (error)
- return (error);
-
- pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
- "Allow use of vmm in a jail.");
+ if (error == 0)
+ pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
+ "Allow use of vmm in a jail.");
+ sx_xunlock(&vmmdev_mtx);
- return (0);
+ return (error);
}
int
vmmdev_cleanup(void)
{
- int error;
-
- if (SLIST_EMPTY(&head))
- error = 0;
- else
- error = EBUSY;
+ sx_xlock(&vmmdev_mtx);
+ if (!SLIST_EMPTY(&head)) {
+ sx_xunlock(&vmmdev_mtx);
+ return (EBUSY);
+ }
+ if (vmmctl_cdev != NULL) {
+ destroy_dev(vmmctl_cdev);
+ vmmctl_cdev = NULL;
+ }
+ sx_xunlock(&vmmdev_mtx);
- return (error);
+ return (0);
}
static int
diff --git a/sys/riscv/vmm/vmm.c b/sys/riscv/vmm/vmm.c
index f7cbfc1dfea5..96871fc88453 100644
--- a/sys/riscv/vmm/vmm.c
+++ b/sys/riscv/vmm/vmm.c
@@ -259,21 +259,26 @@ vmm_handler(module_t mod, int what, void *arg)
switch (what) {
case MOD_LOAD:
- /* TODO: check if has_hyp here? */
error = vmmdev_init();
if (error != 0)
break;
error = vmm_init();
if (error == 0)
vmm_initialized = true;
+ else
+ (void)vmmdev_cleanup();
break;
case MOD_UNLOAD:
- /* TODO: check if has_hyp here? */
error = vmmdev_cleanup();
if (error == 0 && vmm_initialized) {
error = vmmops_modcleanup();
- if (error)
+ if (error) {
+ /*
+ * Something bad happened - prevent new
+ * VMs from being created
+ */
vmm_initialized = false;
+ }
}
break;
default: