mirror of
https://github.com/slackhq/nebula.git
synced 2026-08-16 08:26:59 +02:00
overlay/tio: error on multi-segment WriteGSO with a bogus IP version
gsoTypeFromProto returns GSO_NONE when the IP version nibble is neither 4 nor 6, so a multi-fragment superpacket went out as one silent jumbo GSO_NONE packet -- exactly the silent mis-emission the geometry checks promise not to allow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ugV2edVqoz3tBvq9J6yWp
This commit is contained in:
@@ -358,6 +358,12 @@ func (r *Offload) WriteGSO(hdr []byte, transportHdr []byte, pays [][]byte, proto
|
|||||||
gsoType := uint8(unix.VIRTIO_NET_HDR_GSO_NONE)
|
gsoType := uint8(unix.VIRTIO_NET_HDR_GSO_NONE)
|
||||||
if len(pays) > 1 {
|
if len(pays) > 1 {
|
||||||
gsoType = gsoTypeFromProto(proto, hdr[0]>>4)
|
gsoType = gsoTypeFromProto(proto, hdr[0]>>4)
|
||||||
|
if gsoType == unix.VIRTIO_NET_HDR_GSO_NONE {
|
||||||
|
// gsoTypeFromProto only yields GSO_NONE for a bogus IP version
|
||||||
|
// nibble. A multi-segment superpacket must carry a real GSO type,
|
||||||
|
// or the kernel would deliver it as a single jumbo packet.
|
||||||
|
return fmt.Errorf("tio: WriteGSO IP version %d is not GSO-capable", hdr[0]>>4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var gsoSize uint16
|
var gsoSize uint16
|
||||||
if gsoType != unix.VIRTIO_NET_HDR_GSO_NONE {
|
if gsoType != unix.VIRTIO_NET_HDR_GSO_NONE {
|
||||||
|
|||||||
@@ -997,6 +997,8 @@ func TestWriteGSORejectsBadGeometry(t *testing.T) {
|
|||||||
{"undersize-middle-fragment", ipHdr, udpHdr, [][]byte{seg, make([]byte, 100), seg}, GSOProtoUDP, true},
|
{"undersize-middle-fragment", ipHdr, udpHdr, [][]byte{seg, make([]byte, 100), seg}, GSOProtoUDP, true},
|
||||||
{"oversize-last-fragment", ipHdr, tcpHdr, [][]byte{seg, make([]byte, 1201)}, GSOProtoTCP, true},
|
{"oversize-last-fragment", ipHdr, tcpHdr, [][]byte{seg, make([]byte, 1201)}, GSOProtoTCP, true},
|
||||||
{"short-last-fragment-ok", ipHdr, udpHdr, [][]byte{seg, seg, make([]byte, 100)}, GSOProtoUDP, false},
|
{"short-last-fragment-ok", ipHdr, udpHdr, [][]byte{seg, seg, make([]byte, 100)}, GSOProtoUDP, false},
|
||||||
|
{"multi-segment-bad-ip-version", []byte{0x05}, udpHdr, [][]byte{seg, seg}, GSOProtoUDP, true},
|
||||||
|
{"single-segment-bad-ip-version-ok", []byte{0x05}, udpHdr, [][]byte{seg}, GSOProtoUDP, false},
|
||||||
{"no-pays-noop", ipHdr, udpHdr, nil, GSOProtoUDP, false},
|
{"no-pays-noop", ipHdr, udpHdr, nil, GSOProtoUDP, false},
|
||||||
{"valid-udp", ipHdr, udpHdr, [][]byte{seg, seg}, GSOProtoUDP, false},
|
{"valid-udp", ipHdr, udpHdr, [][]byte{seg, seg}, GSOProtoUDP, false},
|
||||||
{"valid-tcp", ipHdr, tcpHdr, [][]byte{seg, seg}, GSOProtoTCP, false},
|
{"valid-tcp", ipHdr, tcpHdr, [][]byte{seg, seg}, GSOProtoTCP, false},
|
||||||
|
|||||||
Reference in New Issue
Block a user