Ignore the length field when processing the experiment extension header.

Reported-by: syzbot+9970c3c1f330bc544966@syzkaller.appspotmail.com
PiperOrigin-RevId: 703588249
This commit is contained in:
Lucas Manning
2024-12-06 12:57:06 -08:00
committed by gVisor bot
parent dc24ae5c71
commit ddaa99e5d4
+12 -12
View File
@@ -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))
}