{"record":{"id":"22cce0bb82e9febf","repo":"slackhq/nebula","slug":"packet-is-too-short","errorCode":null,"errorMessage":"packet is too short","messagePattern":"packet is too short","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"overlay/tio/virtio/segment_linux.go","lineNumber":134,"sourceCode":"\t\t}\n\t}\n\n\treturn nil\n}\n\n// CorrectHdrLen rewrites hdr.HdrLen based on the actual transport header length read out of pkt.\n// The kernel's hdr.HdrLen on the FORWARD path can be the length of the entire first packet, so we don't trust it.\nfunc CorrectHdrLen(pkt []byte, hdr *Hdr) error {\n\t// Thank you wireguard-go for documenting these edge-cases\n\t// Don't trust hdr.hdrLen from the kernel as it can be equal to the length\n\t// of the entire first packet when the kernel is handling it as part of a FORWARD path.\n\t// Instead, parse the transport header length and add it onto csumStart, which is synonymous for IP header length.\n\n\tif hdr.GSOType() == unix.VIRTIO_NET_HDR_GSO_UDP_L4 {\n\t\thdr.HdrLen = hdr.CsumStart + 8\n\t} else {\n\t\tif len(pkt) <= int(hdr.CsumStart+tcpDataOffOff) {\n\t\t\treturn errors.New(\"packet is too short\")\n\t\t}\n\n\t\ttcpHLen := uint16(pkt[hdr.CsumStart+tcpDataOffOff] >> 4 * 4)\n\t\tif tcpHLen < tcpHeaderMinLen || tcpHLen > tcpHeaderMaxLen {\n\t\t\treturn fmt.Errorf(\"tcp header len is invalid: %d\", tcpHLen)\n\t\t}\n\t\thdr.HdrLen = hdr.CsumStart + tcpHLen\n\t}\n\n\tif len(pkt) < int(hdr.HdrLen) {\n\t\treturn fmt.Errorf(\"length of packet (%d) < virtioNetHdr.HdrLen (%d)\", len(pkt), hdr.HdrLen)\n\t}\n\n\tif hdr.HdrLen < hdr.CsumStart {\n\t\treturn fmt.Errorf(\"virtioNetHdr.HdrLen (%d) < virtioNetHdr.CsumStart (%d)\", hdr.HdrLen, hdr.CsumStart)\n\t}\n\tcSumAt := int(hdr.CsumStart + hdr.CsumOffset)\n\tif cSumAt+1 >= len(pkt) {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tio/virtio/segment_linux.go#L116-L152","documentation":"CorrectHdrLen returns errors.New(\"packet is too short\") when the packet is not long enough to contain the TCP data-offset byte at hdr.CsumStart+tcpDataOffOff, so the transport header length cannot be computed for a GSO packet. This is a sibling guard to errPacketTooShort but is an ad-hoc errors.New raised inside the public CorrectHdrLen path (called by decodeRead).","triggerScenarios":"CorrectHdrLen is called on a packet where len(pkt) <= int(hdr.CsumStart+tcpDataOffOff), i.e. the buffer ends before the TCP header's data-offset field. Reached via decodeRead when a received GSO frame is truncated or CsumStart is bogus.","commonSituations":"Malformed packets delivered on the Rx path with inconsistent virtio header metadata; truncated reads from the tun/tap device; CsumStart miscomputed by an earlier parse; hostile local traffic crafting short frames.","solutions":["Validate len(pkt) against hdr.CsumStart + TCP header start before calling CorrectHdrLen.","Verify CsumStart/HdrLen values in the virtio header are sane for the received frame.","Drop the packet and continue the read loop instead of propagating the error up decodeRead.","Consolidate with errPacketTooShort sentinel so callers can errors.Is-match instead of string comparison.","Capture the packet hex dump on occurrence to identify the traffic source producing short frames."],"exampleFix":"// before: ad-hoc error string\nreturn errors.New(\"packet is too short\")\n// after: sentinel error comparable with errors.Is\nvar errPacketTooShort = errors.New(\"packet is too short\")\nif len(pkt) <= int(hdr.CsumStart+tcpDataOffOff) {\n    return errPacketTooShort\n}","handlingStrategy":"validation","validationCode":"if len(pkt) <= int(hdr.CsumStart+tcpDataOffOff) {\n    stats.Malformed++\n    return // cannot read TCP data offset\n}","typeGuard":null,"tryCatchPattern":"if err := seg.CorrectHdrLen(pkt, hdr); err != nil {\n    if strings.Contains(err.Error(), \"packet is too short\") {\n        stats.Malformed++\n        continue // drop frame, keep read loop alive\n    }\n    return err\n}","preventionTips":["Sanity-check virtio hdr.CsumStart/HdrLen against actual packet length before CorrectHdrLen.","Replace ad-hoc errors.New with a sentinel (errPacketTooShort) for errors.Is matching.","Drop short frames inside decodeRead instead of propagating I/O errors to callers.","Capture hex dumps of offending frames to trace the emitting source."],"tags":["linux","virtio","tcp","packet-parsing","network"],"backgroundTag":"packet-too-short","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}