diff options
| author | Mark Peek <mp@FreeBSD.org> | 2021-10-09 21:21:16 +0000 |
|---|---|---|
| committer | Mark Peek <mp@FreeBSD.org> | 2021-10-16 18:22:43 +0000 |
| commit | 4e5c1be4202a141b7a15c505848abcbea535912f (patch) | |
| tree | 1a70199f1c45a79d7d790a9d043fd41e9ece31d4 | |
| parent | 66f5f958646c780676c23bd581cf5b3e26eff551 (diff) | |
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
(cherry picked from commit 0f14bcbe384091c729464cb770372aeb79061070)
| -rw-r--r-- | sys/dev/vmware/vmci/vmci.c | 9 | ||||
| -rw-r--r-- | sys/dev/vmware/vmci/vmci_event.c | 3 | ||||
| -rw-r--r-- | sys/dev/vmware/vmci/vmci_kernel_if.c | 48 | ||||
| -rw-r--r-- | sys/dev/vmware/vmci/vmci_kernel_if.h | 2 | ||||
| -rw-r--r-- | 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); } /* @@ -168,6 +169,29 @@ vmci_release_lock_bh(vmci_lock *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); +} + +/* + *------------------------------------------------------------------------------ + * * vmci_alloc_kernel_mem * * Allocate physically contiguous memory for the VMCI driver. @@ -449,6 +473,28 @@ vmci_mutex_release(vmci_mutex *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); +} +/* + *------------------------------------------------------------------------------ + * * vmci_alloc_queue -- * * Allocates kernel queue pages of specified size with IOMMU mappings, plus 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 = |
