Report correct pointer value for "bad next header" ICMP error
Because the code handles a bad header as "payload" right up to the last moment we need to make sure payload handling does not remove the error information. Fixes #4909 PiperOrigin-RevId: 344141690
This commit is contained in:
parent
f90ab60a8a
commit
4da63dc82e
|
@ -47,6 +47,11 @@ const (
|
|||
// IPv6NoNextHeaderIdentifier is the header identifier used to signify the end
|
||||
// of an IPv6 payload, as per RFC 8200 section 4.7.
|
||||
IPv6NoNextHeaderIdentifier IPv6ExtensionHeaderIdentifier = 59
|
||||
|
||||
// IPv6UnknownExtHdrIdentifier is reserved by IANA.
|
||||
// https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#extension-header
|
||||
// "254 Use for experimentation and testing [RFC3692][RFC4727]"
|
||||
IPv6UnknownExtHdrIdentifier IPv6ExtensionHeaderIdentifier = 254
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -452,9 +457,11 @@ func (i *IPv6PayloadIterator) AsRawHeader(consume bool) IPv6RawPayloadHeader {
|
|||
// Since we consume the iterator, we return the payload as is.
|
||||
buf = i.payload
|
||||
|
||||
// Mark i as done.
|
||||
// Mark i as done, but keep track of where we were for error reporting.
|
||||
*i = IPv6PayloadIterator{
|
||||
nextHdrIdentifier: IPv6NoNextHeaderIdentifier,
|
||||
headerOffset: i.headerOffset,
|
||||
nextOffset: i.nextOffset,
|
||||
}
|
||||
} else {
|
||||
buf = i.payload.Clone(nil)
|
||||
|
|
|
@ -34,7 +34,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// ReassembleTimeout controls how long a fragment will be held.
|
||||
// As per RFC 8200 section 4.5:
|
||||
//
|
||||
// If insufficient fragments are received to complete reassembly of a packet
|
||||
// within 60 seconds of the reception of the first-arriving fragment of that
|
||||
// packet, reassembly of that packet must be abandoned.
|
||||
|
@ -1092,9 +1094,16 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
|
|||
//
|
||||
// Which when taken together indicate that an unknown protocol should
|
||||
// be treated as an unrecognized next header value.
|
||||
// The location of the Next Header field is in a different place in
|
||||
// the initial IPv6 header than it is in the extension headers so
|
||||
// treat it specially.
|
||||
prevHdrIDOffset := uint32(header.IPv6NextHeaderOffset)
|
||||
if previousHeaderStart != 0 {
|
||||
prevHdrIDOffset = previousHeaderStart
|
||||
}
|
||||
_ = e.protocol.returnError(&icmpReasonParameterProblem{
|
||||
code: header.ICMPv6UnknownHeader,
|
||||
pointer: it.ParseOffset(),
|
||||
pointer: prevHdrIDOffset,
|
||||
}, pkt)
|
||||
default:
|
||||
panic(fmt.Sprintf("unrecognized result from DeliverTransportPacket = %d", res))
|
||||
|
@ -1102,12 +1111,11 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
|
|||
}
|
||||
|
||||
default:
|
||||
_ = e.protocol.returnError(&icmpReasonParameterProblem{
|
||||
code: header.ICMPv6UnknownHeader,
|
||||
pointer: it.ParseOffset(),
|
||||
}, pkt)
|
||||
stats.UnknownProtocolRcvdPackets.Increment()
|
||||
return
|
||||
// Since the iterator returns IPv6RawPayloadHeader for unknown Extension
|
||||
// Header IDs this should never happen unless we missed a supported type
|
||||
// here.
|
||||
panic(fmt.Sprintf("unrecognized type from it.Next() = %T", extHdr))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ const (
|
|||
fragmentExtHdrID = uint8(header.IPv6FragmentExtHdrIdentifier)
|
||||
destinationExtHdrID = uint8(header.IPv6DestinationOptionsExtHdrIdentifier)
|
||||
noNextHdrID = uint8(header.IPv6NoNextHeaderIdentifier)
|
||||
unknownHdrID = uint8(header.IPv6UnknownExtHdrIdentifier)
|
||||
|
||||
extraHeaderReserve = 50
|
||||
)
|
||||
|
@ -572,6 +573,33 @@ func TestReceiveIPv6ExtHdrs(t *testing.T) {
|
|||
shouldAccept: false,
|
||||
expectICMP: false,
|
||||
},
|
||||
{
|
||||
name: "unknown next header (first)",
|
||||
extHdr: func(nextHdr uint8) ([]byte, uint8) {
|
||||
return []byte{
|
||||
nextHdr, 0, 63, 4, 1, 2, 3, 4,
|
||||
}, unknownHdrID
|
||||
},
|
||||
shouldAccept: false,
|
||||
expectICMP: true,
|
||||
ICMPType: header.ICMPv6ParamProblem,
|
||||
ICMPCode: header.ICMPv6UnknownHeader,
|
||||
pointer: header.IPv6NextHeaderOffset,
|
||||
},
|
||||
{
|
||||
name: "unknown next header (not first)",
|
||||
extHdr: func(nextHdr uint8) ([]byte, uint8) {
|
||||
return []byte{
|
||||
unknownHdrID, 0,
|
||||
63, 4, 1, 2, 3, 4,
|
||||
}, hopByHopExtHdrID
|
||||
},
|
||||
shouldAccept: false,
|
||||
expectICMP: true,
|
||||
ICMPType: header.ICMPv6ParamProblem,
|
||||
ICMPCode: header.ICMPv6UnknownHeader,
|
||||
pointer: header.IPv6FixedHeaderSize,
|
||||
},
|
||||
{
|
||||
name: "destination with unknown option skippable action",
|
||||
extHdr: func(nextHdr uint8) ([]byte, uint8) {
|
||||
|
@ -754,11 +782,6 @@ func TestReceiveIPv6ExtHdrs(t *testing.T) {
|
|||
ICMPCode: header.ICMPv6UnknownHeader,
|
||||
pointer: header.IPv6FixedHeaderSize,
|
||||
},
|
||||
{
|
||||
name: "No next header",
|
||||
extHdr: func(nextHdr uint8) ([]byte, uint8) { return []byte{}, noNextHdrID },
|
||||
shouldAccept: false,
|
||||
},
|
||||
{
|
||||
name: "hopbyhop (with skippable unknown) - routing - atomic fragment - destination (with skippable unknown)",
|
||||
extHdr: func(nextHdr uint8) ([]byte, uint8) {
|
||||
|
|
|
@ -243,8 +243,6 @@ ALL_TESTS = [
|
|||
),
|
||||
PacketimpactTestInfo(
|
||||
name = "icmpv6_param_problem",
|
||||
# TODO(b/153485026): Fix netstack then remove the line below.
|
||||
expect_netstack_failure = True,
|
||||
),
|
||||
PacketimpactTestInfo(
|
||||
name = "ipv6_unknown_options_action",
|
||||
|
|
Loading…
Reference in New Issue