DragonFlyBSD Kernel Audit
DF-1214 / fix.diff
← back to finding ↓ download raw
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",