⬢ DragonFlyBSD Kernel Audit
DF-3779 / 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
@@ -2221,6 +2221,17 @@ vmxnet3_rxq_eof(struct vmxnet3_rxqueue *r
 		rxd = &rxr->vxrxr_rxd[idx];
 
 		m = rxr->vxrxr_rxbuf[idx].vrxb_m;
 		KASSERT(m != NULL, ("%s: queue %d idx %d without mbuf",
 		    __func__, rxcd->qid, idx));
+
+		/*
+		 * DF-3779: rxcd->qid is host-supplied and selects the
+		 * buffer ring.  Ring 1 is left unpopulated (all vrxb_m
+		 * NULL) unless the frame size forces the second ring, so a
+		 * hostile host steering a completion to it drives a NULL
+		 * mbuf dereference below.  Drop the completion instead.
+		 */
+		if (m == NULL) {
+			rxq->vxrxq_stats.vmrxs_iqdrops++;
+			vmxnet3_rxq_eof_discard(rxq, rxr, idx % rxr->vxrxr_ndesc);
+			goto nextp;
+		}
 
 		/*
 		 * The host may skip descriptors. We detect this when this
 		 * descriptor does not match the previous fill index. Catch
*** VERDICT NOTE (not part of the diff): the identical ring-selection
*** pattern exists in vmxnet3_rxq_discard_chain() (if_vmx.c:2086-2089);
*** vmxnet3_rxq_eof_discard() there only writes rxd->gen, which is
*** harmless for a NULL-mbuf ring, so no extra guard is required there
*** once idx is bounded (DF-1213).