From ddaa99e5d4d2179674e81fee5e3696df7e120aa5 Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Fri, 6 Dec 2024 12:53:26 -0800 Subject: [PATCH] Ignore the length field when processing the experiment extension header. Reported-by: syzbot+9970c3c1f330bc544966@syzkaller.appspotmail.com PiperOrigin-RevId: 703588249 --- pkg/tcpip/header/ipv6_extension_headers.go | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/tcpip/header/ipv6_extension_headers.go b/pkg/tcpip/header/ipv6_extension_headers.go index 110f5c63c..1359f9954 100644 --- a/pkg/tcpip/header/ipv6_extension_headers.go +++ b/pkg/tcpip/header/ipv6_extension_headers.go @@ -595,7 +595,7 @@ func (i *IPv6PayloadIterator) Next() (IPv6PayloadHeader, bool, error) { // Is the header we are parsing a known extension header? switch i.nextHdrIdentifier { case IPv6HopByHopOptionsExtHdrIdentifier: - nextHdrIdentifier, view, err := i.nextHeaderData(false /* fragmentHdr */, nil) + nextHdrIdentifier, view, err := i.nextHeaderData(false /* ignoreLength */, nil) if err != nil { return nil, true, err } @@ -603,7 +603,7 @@ func (i *IPv6PayloadIterator) Next() (IPv6PayloadHeader, bool, error) { i.nextHdrIdentifier = nextHdrIdentifier return IPv6HopByHopOptionsExtHdr{ipv6OptionsExtHdr{view}}, false, nil case IPv6RoutingExtHdrIdentifier: - nextHdrIdentifier, view, err := i.nextHeaderData(false /* fragmentHdr */, nil) + nextHdrIdentifier, view, err := i.nextHeaderData(false /* ignoreLength */, nil) if err != nil { return nil, true, err } @@ -614,7 +614,7 @@ func (i *IPv6PayloadIterator) Next() (IPv6PayloadHeader, bool, error) { var data [6]byte // We ignore the returned bytes because we know the fragment extension // header specific data will fit in data. - nextHdrIdentifier, _, err := i.nextHeaderData(true /* fragmentHdr */, data[:]) + nextHdrIdentifier, _, err := i.nextHeaderData(true /* ignoreLength */, data[:]) if err != nil { return nil, true, err } @@ -633,7 +633,7 @@ func (i *IPv6PayloadIterator) Next() (IPv6PayloadHeader, bool, error) { i.nextHdrIdentifier = nextHdrIdentifier return fragmentExtHdr, false, nil case IPv6DestinationOptionsExtHdrIdentifier: - nextHdrIdentifier, view, err := i.nextHeaderData(false /* fragmentHdr */, nil) + nextHdrIdentifier, view, err := i.nextHeaderData(false /* ignoreLength */, nil) if err != nil { return nil, true, err } @@ -642,7 +642,7 @@ func (i *IPv6PayloadIterator) Next() (IPv6PayloadHeader, bool, error) { return IPv6DestinationOptionsExtHdr{ipv6OptionsExtHdr{view}}, false, nil case IPv6ExperimentExtHdrIdentifier: var data [IPv6ExperimentHdrLength - ipv6ExperimentHdrValueOffset]byte - nextHdrIdentifier, _, err := i.nextHeaderData(false /* fragmentHdr */, data[:]) + nextHdrIdentifier, _, err := i.nextHeaderData(true /* ignoreLength */, data[:]) if err != nil { return nil, true, err } @@ -670,14 +670,14 @@ func (i *IPv6PayloadIterator) NextHeaderIdentifier() IPv6ExtensionHeaderIdentifi // nextHeaderData returns the extension header's Next Header field and raw data. // -// fragmentHdr indicates that the extension header being parsed is the Fragment -// extension header so the Length field should be ignored as it is Reserved -// for the Fragment extension header. +// ignoreLength indicates that the extension header being parsed should ignore +// the Length field as it is reserved. This is for the Fragment and Experiment +// extension headers. // // If bytes is not nil, extension header specific data will be read into bytes // if it has enough capacity. If bytes is provided but does not have enough // capacity for the data, nextHeaderData will panic. -func (i *IPv6PayloadIterator) nextHeaderData(fragmentHdr bool, bytes []byte) (IPv6ExtensionHeaderIdentifier, *buffer.View, error) { +func (i *IPv6PayloadIterator) nextHeaderData(ignoreLength bool, bytes []byte) (IPv6ExtensionHeaderIdentifier, *buffer.View, error) { // We ignore the number of bytes read because we know we will only ever read // at max 1 bytes since rune has a length of 1. If we read 0 bytes, the Read // would return io.EOF to indicate that io.Reader has reached the end of the @@ -693,13 +693,13 @@ func (i *IPv6PayloadIterator) nextHeaderData(fragmentHdr bool, bytes []byte) (IP length, err = rdr.ReadByte() if err != nil { - if fragmentHdr { + if ignoreLength { return 0, nil, fmt.Errorf("error when reading the Length field for extension header with id = %d: %w", i.nextHdrIdentifier, err) } return 0, nil, fmt.Errorf("error when reading the Reserved field for extension header with id = %d: %w", i.nextHdrIdentifier, err) } - if fragmentHdr { + if ignoreLength { length = 0 } @@ -715,7 +715,7 @@ func (i *IPv6PayloadIterator) nextHeaderData(fragmentHdr bool, bytes []byte) (IP i.nextOffset += uint32((length + 1) * ipv6ExtHdrLenBytesPerUnit) bytesLen := int(length)*ipv6ExtHdrLenBytesPerUnit + ipv6ExtHdrLenBytesExcluded - if bytes != nil { + if ignoreLength { if n := len(bytes); n < bytesLen { panic(fmt.Sprintf("bytes only has space for %d bytes but need space for %d bytes (length = %d) for extension header with id = %d", n, bytesLen, length, i.nextHdrIdentifier)) }