[handler] bound encap inner packet and fix MTU header-length undercount (APO-665, APO-667)#2
Merged
Merged
Conversation
…nt (APO-665, APO-667) Two data-plane correctness/safety fixes in the encap path. APO-665 (MTU): headerLength() built the Geneve header literal with both options populated but left NumOptions at 0, so MarshalBinary skipped the option loop and returned the 8-byte base length. MTU() therefore under-counted encapsulation overhead by 24 bytes and over-advertised the virtual-network MTU, letting the inner stack emit packets whose encapsulated size exceeds the path MTU (fragmentation / black-holing). Set NumOptions: 2 to match the fixed 2-option header the datapath emits (geneveHdrLen = 32). APO-667 (encap overflow): neither encap path bounded the inner IP packet, so AES-GCM Seal (ciphertext + 16-byte tag) could be written past the end of the destination frame. On the AF_XDP datapath FrameFull caps the slice, so an oversized inner packet forces Seal to silently reallocate onto the heap -- leaving plaintext in the UMEM frame the descriptor still points at; an external EngineXfrm/vtep caller passing a buffer whose capacity spans the next frame gets the literal adjacent-memory write. Both data-carrying encap paths (VirtToPhyInPlace, VirtToPhy) now drop and count a TX error when inner+tag would not fit. The keep-alive seals carry an empty plaintext and are unaffected. Tests: util_test.go pins headerLength()/MTU() against the full overhead; oversized_inner_test.go drives an inner packet sized so the tag spills the frame edge and asserts a drop with an intact canary in the buffer tail (plus a boundary case that the max-sized packet still encapsulates). All four fail without the fixes. go vet, root go test, and GOOS=linux build are green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two data-plane correctness/safety fixes in the encap path.
APO-665 (MTU)
headerLength()built the Geneve header literal with both options populated but leftNumOptionsat 0, soMarshalBinaryskipped the option loop and returned the 8-byte base length.MTU()therefore under-counted encapsulation overhead by 24 bytes and over-advertised the virtual-network MTU, letting the inner stack emit packets whose encapsulated size exceeds the path MTU (fragmentation / black-holing). SetNumOptions: 2to match the fixed 2-option header the datapath emits (geneveHdrLen = 32).APO-667 (encap overflow)
Neither encap path bounded the inner IP packet, so AES-GCM
Seal(ciphertext + 16-byte tag) could be written past the end of the destination frame. On the AF_XDP datapathFrameFullcaps the slice, so an oversized inner packet forcesSealto silently reallocate onto the heap — leaving plaintext in the UMEM frame the descriptor still points at; an externalEngineXfrm/vtep caller passing a buffer whose capacity spans the next frame gets the literal adjacent-memory write. Both data-carrying encap paths (VirtToPhyInPlace,VirtToPhy) now drop and count a TX error when inner+tag would not fit. The keep-alive seals carry an empty plaintext and are unaffected.Tests
util_test.gopinsheaderLength()/MTU()against the full overhead;oversized_inner_test.godrives an inner packet sized so the tag spills the frame edge and asserts a drop with an intact canary in the buffer tail (plus a boundary case that the max-sized packet still encapsulates). All four fail without the fixes.go vet, rootgo test, andGOOS=linuxbuild are green.🤖 Generated with Claude Code