DF-3779 / fix.diff
--- 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). |