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 <t-kus...@iij.ad.jp>


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);

Reply via email to