diff --git a/sys/dev/virtual/vmware/vmxnet3/if_vmx.c b/sys/dev/virtual/vmware/vmxnet3/if_vmx.c --- a/sys/dev/virtual/vmware/vmxnet3/if_vmx.c +++ b/sys/dev/virtual/vmware/vmxnet3/if_vmx.c @@ -2219,6 +2219,21 @@ else rxr = &rxq->vxrxq_cmd_ring[1]; rxd = &rxr->vxrxr_rxd[idx]; + /* + * rxcd->len is a 14-bit field supplied by the hypervisor + * (0..16383) and is written verbatim into m_len / m_pkthdr.len + * below. HEAD descriptors are backed by an MCLBYTES cluster + * (only MCLBYTES - ETHER_ALIGN bytes are usable after m_adj) + * and BODY descriptors by an MJUMPAGESIZE cluster. Clamp any + * length that exceeds the backing cluster so a malicious or + * buggy host cannot make if_input() walk past the cluster into + * adjacent kernel heap (guest info leak / corruption). + */ + if (rxd->btype == VMXNET3_BTYPE_HEAD) { + if (length > MCLBYTES - ETHER_ALIGN) + length = MCLBYTES - ETHER_ALIGN; + } else if (length > MJUMPAGESIZE) + length = MJUMPAGESIZE; m = rxr->vxrxr_rxbuf[idx].vrxb_m; KASSERT(m != NULL, ("%s: queue %d idx %d without mbuf",