{"record":{"id":"a92ba92f3e60e133","repo":"slackhq/nebula","slug":"end-of-checksum-offset-d-exceeds-packet-length","errorCode":null,"errorMessage":"end of checksum offset (%d) exceeds packet length (%d)","messagePattern":"end of checksum offset \\((.+?)\\) exceeds packet length \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tio/virtio/segment_linux.go","lineNumber":153,"sourceCode":"\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) {\n\t\treturn fmt.Errorf(\"end of checksum offset (%d) exceeds packet length (%d)\", cSumAt+1, len(pkt))\n\t}\n\treturn nil\n}\n\n// segCount returns how many segments a payload of payLen bytes splits into at gsoSize,\n// with a floor of one so a header-only superpacket still yields a single segment.\nfunc segCount(payLen, gsoSize int) int {\n\tn := (payLen + gsoSize - 1) / gsoSize\n\tif n == 0 {\n\t\treturn 1\n\t}\n\treturn n\n}\n\n// basePseudoSum folds the part of the L4 pseudo-header sum that is identical\n// for every segment: the source and destination addresses plus the protocol\n// number. The per-segment L4 length is added by the caller inside the loop.\nfunc basePseudoSum(pkt []byte, isV4 bool, proto uint32) uint32 {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tio/virtio/segment_linux.go#L135-L171","documentation":"Packet-validation error in CorrectHdrLen (virtio receive path): the two-byte checksum field at CsumStart+CsumOffset would end past the end of the packet. The virtioNetHdr offsets from the kernel point outside the actual buffer, so the checksum cannot be fixed up; both the computed end offset and packet length are reported.","triggerScenarios":"Thrown at overlay/tio/virtio/segment_linux.go:153 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Drop the malformed packet and let upper layers retransmit","Treat as a kernel/virtio negotiation mismatch: check TUNSETOFFLOAD vs negotiated vnet header size","Capture the packet and hdr fields to diagnose the off-by-N in CsumStart/CsumOffset"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}