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