Validate router alert's data length

RFC 2711 specifies that the router alert's length field is always 2
so we should make sure only 2 bytes are read from a router alert
option's data field.

Test: header.TestIPv6OptionsExtHdrIterErr
PiperOrigin-RevId: 347727876
This commit is contained in:
Ghanan Gowripalan
2020-12-15 17:45:22 -08:00
committed by gVisor bot
parent 97406b20a1
commit c55e5bda4d
2 changed files with 39 additions and 4 deletions
+14 -4
View File
@@ -18,6 +18,7 @@ import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math"
@@ -274,6 +275,10 @@ func ipv6UnknownActionFromIdentifier(id IPv6ExtHdrOptionIdentifier) IPv6OptionUn
return IPv6OptionUnknownAction((id & ipv6UnknownExtHdrOptionActionMask) >> ipv6UnknownExtHdrOptionActionShift)
}
// ErrMalformedIPv6ExtHdrOption indicates that an IPv6 extension header option
// is malformed.
var ErrMalformedIPv6ExtHdrOption = errors.New("malformed IPv6 extension header option")
// IPv6UnknownExtHdrOption holds the identifier and data for an IPv6 extension
// header option that is unknown by the parsing utilities.
type IPv6UnknownExtHdrOption struct {
@@ -351,10 +356,15 @@ func (i *IPv6OptionsExtHdrOptionsIterator) Next() (IPv6ExtHdrOption, bool, error
continue
case ipv6RouterAlertHopByHopOptionIdentifier:
var routerAlertValue [ipv6RouterAlertPayloadLength]byte
if n, err := i.reader.Read(routerAlertValue[:]); err != nil {
panic(fmt.Sprintf("error when reading RouterAlert option's data bytes: %s", err))
} else if n != ipv6RouterAlertPayloadLength {
return nil, true, fmt.Errorf("read %d bytes for RouterAlert option, expected %d", n, ipv6RouterAlertPayloadLength)
if n, err := io.ReadFull(&i.reader, routerAlertValue[:]); err != nil {
switch err {
case io.EOF, io.ErrUnexpectedEOF:
return nil, true, fmt.Errorf("got invalid length (%d) for router alert option (want = %d): %w", length, ipv6RouterAlertPayloadLength, ErrMalformedIPv6ExtHdrOption)
default:
return nil, true, fmt.Errorf("read %d out of %d option data bytes for router alert option: %w", n, ipv6RouterAlertPayloadLength, err)
}
} else if n != int(length) {
return nil, true, fmt.Errorf("got invalid length (%d) for router alert option (want = %d): %w", length, ipv6RouterAlertPayloadLength, ErrMalformedIPv6ExtHdrOption)
}
return &IPv6RouterAlertOption{Value: IPv6RouterAlertValue(binary.BigEndian.Uint16(routerAlertValue[:]))}, false, nil
default:
@@ -212,6 +212,31 @@ func TestIPv6OptionsExtHdrIterErr(t *testing.T) {
bytes: []byte{1, 3},
err: io.ErrUnexpectedEOF,
},
{
name: "Router alert without data",
bytes: []byte{byte(ipv6RouterAlertHopByHopOptionIdentifier), 0},
err: ErrMalformedIPv6ExtHdrOption,
},
{
name: "Router alert with partial data",
bytes: []byte{byte(ipv6RouterAlertHopByHopOptionIdentifier), 1, 1},
err: ErrMalformedIPv6ExtHdrOption,
},
{
name: "Router alert with partial data and Pad1",
bytes: []byte{byte(ipv6RouterAlertHopByHopOptionIdentifier), 1, 1, 0},
err: ErrMalformedIPv6ExtHdrOption,
},
{
name: "Router alert with extra data",
bytes: []byte{byte(ipv6RouterAlertHopByHopOptionIdentifier), 3, 1, 2, 3},
err: ErrMalformedIPv6ExtHdrOption,
},
{
name: "Router alert with missing data",
bytes: []byte{byte(ipv6RouterAlertHopByHopOptionIdentifier), 1},
err: io.ErrUnexpectedEOF,
},
}
check := func(t *testing.T, it IPv6OptionsExtHdrOptionsIterator, expectedErr error) {