git: 0f14bcbe3840 - main - vmci: fix panic due to freeing unallocated resources
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 09 Oct 2021 21:30:08 UTC
The branch main has been updated by mp:
URL: https://cgit.FreeBSD.org/src/commit/?id=0f14bcbe384091c729464cb770372aeb79061070
commit 0f14bcbe384091c729464cb770372aeb79061070
Author: Mark Peek <mp@FreeBSD.org>
AuthorDate: 2021-10-09 21:21:16 +0000
Commit: Mark Peek <mp@FreeBSD.org>
CommitDate: 2021-10-09 21:21:16 +0000
vmci: fix panic due to freeing unallocated resources
Summary:
An error mapping PCI resources results in a panic due to unallocated
resources being freed up. This change puts the appropriate checks in
place to prevent the panic.
PR: 252445
Reported by: Marek Zarychta <zarychtam@plan-b.pwste.edu.pl>
Tested by: marcus
MFC after: 1 week
Sponsored by: VMware
Test Plan:
Along with user testing, also simulated error by inserting a ENXIO
return in vmci_map_bars().
Reviewed by: marcus
Subscribers: imp
Differential Revision: https://reviews.freebsd.org/D32016
---
sys/dev/vmware/vmci/vmci.c | 9 ++++---
sys/dev/vmware/vmci/vmci_event.c | 3 +++
sys/dev/vmware/vmci/vmci_kernel_if.c | 48 ++++++++++++++++++++++++++++++++++-
sys/dev/vmware/vmci/vmci_kernel_if.h | 2 ++
sys/dev/vmware/vmci/vmci_queue_pair.c | 3 +++
5 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/sys/dev/vmware/vmci/vmci.c b/sys/dev/vmware/vmci/vmci.c
index bbf17bbe7e41..8adcb7f532b7 100644
--- a/sys/dev/vmware/vmci/vmci.c
+++ b/sys/dev/vmware/vmci/vmci.c
@@ -242,8 +242,10 @@ vmci_detach(device_t dev)
vmci_components_cleanup();
- taskqueue_drain(taskqueue_thread, &sc->vmci_delayed_work_task);
- mtx_destroy(&sc->vmci_delayed_work_lock);
+ if mtx_initialized(&sc->vmci_spinlock) {
+ taskqueue_drain(taskqueue_thread, &sc->vmci_delayed_work_task);
+ mtx_destroy(&sc->vmci_delayed_work_lock);
+ }
if (sc->vmci_res0 != NULL)
bus_space_write_4(sc->vmci_iot0, sc->vmci_ioh0,
@@ -254,7 +256,8 @@ vmci_detach(device_t dev)
vmci_unmap_bars(sc);
- mtx_destroy(&sc->vmci_spinlock);
+ if mtx_initialized(&sc->vmci_spinlock)
+ mtx_destroy(&sc->vmci_spinlock);
pci_disable_busmaster(dev);
diff --git a/sys/dev/vmware/vmci/vmci_event.c b/sys/dev/vmware/vmci/vmci_event.c
index 7f3bf9039e12..192828cc6f6a 100644
--- a/sys/dev/vmware/vmci/vmci_event.c
+++ b/sys/dev/vmware/vmci/vmci_event.c
@@ -593,6 +593,9 @@ vmci_event_unregister_subscription(vmci_id sub_id)
{
struct vmci_subscription *s;
+ if (!vmci_initialized_lock(&subscriber_lock))
+ return NULL;
+
vmci_grab_lock_bh(&subscriber_lock);
s = vmci_event_find(sub_id);
if (s != NULL) {
diff --git a/sys/dev/vmware/vmci/vmci_kernel_if.c b/sys/dev/vmware/vmci/vmci_kernel_if.c
index e845650873b5..de54a8d1ca4f 100644
--- a/sys/dev/vmware/vmci/vmci_kernel_if.c
+++ b/sys/dev/vmware/vmci/vmci_kernel_if.c
@@ -70,7 +70,8 @@ void
vmci_cleanup_lock(vmci_lock *lock)
{
- mtx_destroy(lock);
+ if mtx_initialized(lock)
+ mtx_destroy(lock);
}
/*
@@ -165,6 +166,29 @@ vmci_release_lock_bh(vmci_lock *lock)
mtx_unlock(lock);
}
+/*
+ *------------------------------------------------------------------------------
+ *
+ * vmci_initialized_lock
+ *
+ * Returns whether a lock has been initialized.
+ *
+ * Results:
+ * Return 1 if initialized or 0 if unininitialized.
+ *
+ * Side effects:
+ * None
+ *
+ *------------------------------------------------------------------------------
+ */
+
+int
+vmci_initialized_lock(vmci_lock *lock)
+{
+
+ return mtx_initialized(lock);
+}
+
/*
*------------------------------------------------------------------------------
*
@@ -446,6 +470,28 @@ vmci_mutex_release(vmci_mutex *mutex)
mtx_unlock(mutex);
}
+/*
+ *------------------------------------------------------------------------------
+ *
+ * vmci_mutex_initialized
+ *
+ * Returns whether a mutex has been initialized.
+ *
+ * Results:
+ * Return 1 if initialized or 0 if unininitialized.
+ *
+ * Side effects:
+ * None
+ *
+ *------------------------------------------------------------------------------
+ */
+
+int
+vmci_mutex_initialized(vmci_mutex *mutex)
+{
+
+ return mtx_initialized(mutex);
+}
/*
*------------------------------------------------------------------------------
*
diff --git a/sys/dev/vmware/vmci/vmci_kernel_if.h b/sys/dev/vmware/vmci/vmci_kernel_if.h
index fc23eefe98e0..048e480b0698 100644
--- a/sys/dev/vmware/vmci/vmci_kernel_if.h
+++ b/sys/dev/vmware/vmci/vmci_kernel_if.h
@@ -48,6 +48,7 @@ void vmci_grab_lock(vmci_lock *lock);
void vmci_release_lock(vmci_lock *lock);
void vmci_grab_lock_bh(vmci_lock *lock);
void vmci_release_lock_bh(vmci_lock *lock);
+int vmci_initialized_lock(vmci_lock *lock);
void *vmci_alloc_kernel_mem(size_t size, int flags);
void vmci_free_kernel_mem(void *ptr, size_t size);
@@ -72,6 +73,7 @@ int vmci_mutex_init(vmci_mutex *mutex, char *name);
void vmci_mutex_destroy(vmci_mutex *mutex);
void vmci_mutex_acquire(vmci_mutex *mutex);
void vmci_mutex_release(vmci_mutex *mutex);
+int vmci_mutex_initialized(vmci_mutex *mutex);
void *vmci_alloc_queue(uint64_t size, uint32_t flags);
void vmci_free_queue(void *q, uint64_t size);
diff --git a/sys/dev/vmware/vmci/vmci_queue_pair.c b/sys/dev/vmware/vmci/vmci_queue_pair.c
index 2ff963c691d0..0e2f83b20c67 100644
--- a/sys/dev/vmware/vmci/vmci_queue_pair.c
+++ b/sys/dev/vmware/vmci/vmci_queue_pair.c
@@ -338,6 +338,9 @@ vmci_qp_guest_endpoints_exit(void)
{
struct qp_guest_endpoint *entry;
+ if (!vmci_mutex_initialized(&qp_guest_endpoints.mutex))
+ return;
+
vmci_mutex_acquire(&qp_guest_endpoints.mutex);
while ((entry =