Module Name: src
Committed By: jdolecek
Date: Sun Nov 5 18:21:55 UTC 2023
Modified Files:
src/sys/dev/pci: if_ena.c
src/sys/external/bsd/ena-com: ena_com.c
Log Message:
ena(4): prevent AENQ handler from use-after-free
Code contributed by KUSABA Takeshi <[email protected]>
To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/pci/if_ena.c
cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/ena-com/ena_com.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_ena.c
diff -u src/sys/dev/pci/if_ena.c:1.37 src/sys/dev/pci/if_ena.c:1.38
--- src/sys/dev/pci/if_ena.c:1.37 Sun Nov 5 18:18:56 2023
+++ src/sys/dev/pci/if_ena.c Sun Nov 5 18:21:54 2023
@@ -36,7 +36,7 @@
#if 0
__FBSDID("$FreeBSD: head/sys/dev/ena/ena.c 333456 2018-05-10 09:37:54Z mw $");
#endif
-__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.37 2023/11/05 18:18:56 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.38 2023/11/05 18:21:54 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -3896,21 +3896,8 @@ ena_detach(device_t pdev, int flags)
workqueue_destroy(adapter->reset_tq);
adapter->reset_tq = NULL;
- if (adapter->ifp != NULL) {
- ether_ifdetach(adapter->ifp);
- if_detach(adapter->ifp);
- }
- ifmedia_fini(&adapter->media);
-
ena_free_all_io_rings_resources(adapter);
- ena_free_counters((struct evcnt *)&adapter->hw_stats,
- sizeof(struct ena_hw_stats),
- offsetof(struct ena_hw_stats, rx_packets));
- ena_free_counters((struct evcnt *)&adapter->dev_stats,
- sizeof(struct ena_stats_dev),
- offsetof(struct ena_stats_dev, wd_expired));
-
if (likely(adapter->rss_support))
ena_com_rss_destroy(ena_dev);
@@ -3944,6 +3931,19 @@ ena_detach(device_t pdev, int flags)
ena_free_pci_resources(adapter);
+ ena_free_counters((struct evcnt *)&adapter->hw_stats,
+ sizeof(struct ena_hw_stats),
+ offsetof(struct ena_hw_stats, rx_packets));
+ ena_free_counters((struct evcnt *)&adapter->dev_stats,
+ sizeof(struct ena_stats_dev),
+ offsetof(struct ena_stats_dev, wd_expired));
+
+ if (adapter->ifp != NULL) {
+ ether_ifdetach(adapter->ifp);
+ if_detach(adapter->ifp);
+ }
+ ifmedia_fini(&adapter->media);
+
mutex_destroy(&adapter->global_mtx);
if (ena_dev->bus != NULL)
Index: src/sys/external/bsd/ena-com/ena_com.c
diff -u src/sys/external/bsd/ena-com/ena_com.c:1.2 src/sys/external/bsd/ena-com/ena_com.c:1.3
--- src/sys/external/bsd/ena-com/ena_com.c:1.2 Sun Nov 5 18:15:02 2023
+++ src/sys/external/bsd/ena-com/ena_com.c Sun Nov 5 18:21:54 2023
@@ -1392,6 +1392,12 @@ void ena_com_wait_for_abort_completion(s
struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue;
unsigned long flags;
+ /*
+ * XXX: workaround for missing synchronization mechanism of AENQ handler
+ * Wait 20ms for safety though it have not panicked actually.
+ */
+ ENA_MSLEEP(20);
+
ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags);
while (ATOMIC32_READ(&admin_queue->outstanding_cmds) != 0) {
ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags);