⬢ DragonFlyBSD Kernel Audit
DF-3782 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/virtual/vmware/vmxnet3/if_vmx.c
+++ b/sys/dev/virtual/vmware/vmxnet3/if_vmx.c
@@ -2195,6 +2195,9 @@ vmxnet3_rxq_eof(struct vmxnet3_rxqueue *r
 	struct vmxnet3_rxcompdesc *rxcd;
 	struct mbuf *m, *m_head, *m_tail;
 	int idx, length;
+	int budget = vmxnet3_rx_budget;
 
 	sc = rxq->vxrxq_sc;
 	ifp = sc->vmx_ifp;
@@ -2201,6 +2204,17 @@ vmxnet3_rxq_eof(struct vmxnet3_rxqueue *r
 
 	for (;;) {
+		/*
+		 * DF-3782: bound the completion walk so a host that
+		 * (nominally on behalf of a line-rate remote flood)
+		 * keeps the ring populated cannot livelock the
+		 * interrupt thread holding the RXQ lock.
+		 */
+		if (--budget <= 0) {
+			rxq->vxrxq_mhead = m_head;
+			rxq->vxrxq_mtail = m_tail;
+			rxq->vxrxq_more = 1;
+			break;
+		}
 		rxcd = &rxc->vxcr_u.rxcd[rxc->vxcr_next];
 		if (rxcd->gen != rxc->vxcr_gen) {
 			rxq->vxrxq_mhead = m_head;
*** NOTE 1: adds `int vmxnet3_rx_budget = 256;` (+TUNABLE_INT
*** "hw.vmx.rx_budget") and a `vxrxq_more` flag to struct vmxnet3_rxqueue
*** (if_vmxvar.h); the interrupt handlers must, when vxrxq_more is set,
*** re-arm via callout_reset(&rxq->vxrxq_callout, 1, ...) instead of
*** returning to idle, so already-deposited completions are not stranded.
*** NOTE 2: advisory diff — not validated on hardware (no vmxnet3 device
*** on the audit guest).