Index: /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp	(revision 67974)
+++ /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp	(revision 67975)
@@ -1156,4 +1156,47 @@
 }
 
+static bool vnetReadHeader(PVNETSTATE pThis, RTGCPHYS GCPhys, PVNETHDR pHdr, uint32_t cbMax)
+{
+    int rc = PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), GCPhys, pHdr, sizeof(*pHdr));
+    if (RT_FAILURE(rc))
+        return false;
+
+    Log4(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x csum-start=%x csum-offset=%x cb=%x\n",
+          pHdr->u8Flags, pHdr->u8GSOType, pHdr->u16HdrLen, pHdr->u16GSOSize, pHdr->u16CSumStart, pHdr->u16CSumOffset, cbMax));
+
+    if (pHdr->u8GSOType)
+    {
+        uint32_t u32MinHdrSize;
+
+        /* Segmentation offloading cannot be done without checksumming. */
+        if (RT_UNLIKELY(!(pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)))
+            return false;
+        /* We do not support ECN. */
+        if (RT_UNLIKELY(pHdr->u8GSOType & VNETHDR_GSO_ECN))
+            return false;
+        switch (pHdr->u8GSOType)
+        {
+            case VNETHDR_GSO_TCPV4:
+            case VNETHDR_GSO_TCPV6:
+                u32MinHdrSize = sizeof(RTNETTCP);
+                break;
+            case VNETHDR_GSO_UDP:
+                u32MinHdrSize = 0;
+                break;
+            default:
+                return false;
+        }
+        /* Header+MSS must not exceed the packet size. */
+        if (RT_UNLIKELY(u32MinHdrSize + pHdr->u16CSumStart + pHdr->u16GSOSize > cbMax))
+            return false;
+    }
+    /* Checksum must fit into the frame (validating both checksum fields). */
+    if (   (pHdr->u8Flags & VNETHDR_F_NEEDS_CSUM)
+        && sizeof(uint16_t) + pHdr->u16CSumStart + pHdr->u16CSumOffset > cbMax)
+        return false;
+    Log4(("virtio-net: return true\n"));
+    return true;
+}
+
 static int vnetTransmitFrame(PVNETSTATE pThis, PPDMSCATTERGATHER pSgBuf, PPDMNETWORKGSO pGso, PVNETHDR pHdr)
 {
@@ -1261,4 +1304,5 @@
         else
         {
+            VNETHDR Hdr;
             unsigned int uSize = 0;
             STAM_PROFILE_ADV_START(&pThis->StatTransmit, a);
@@ -1271,11 +1315,7 @@
             if (uSize > VNET_MAX_FRAME_SIZE)
                 uSize = VNET_MAX_FRAME_SIZE;
-            if (pThis->pDrv)
+            if (pThis->pDrv && vnetReadHeader(pThis, elem.aSegsOut[0].addr, &Hdr, uSize))
             {
-                VNETHDR Hdr;
                 PDMNETWORKGSO Gso, *pGso;
-
-                PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[0].addr,
-                                  &Hdr, sizeof(Hdr));
 
                 STAM_REL_COUNTER_INC(&pThis->StatTransmitPackets);
