decode/ipv6: bound hop-by-hop option to the option area

The TLV loop for the IPv6 hop-by-hop and destination option headers
gates each option on (offset + 1 + ip6_optlen) > optslen. An option is
two header bytes (type, length) plus ip6_optlen data bytes, so its data
ends at offset + 1 + ip6_optlen and the bound has to be
offset + 2 + ip6_optlen.

Before: an option that declares its data running one byte past the
option area is accepted, and the Router Alert / Jumbo / Home Address
memcpy then copies sizeof(value) bytes ending one byte past the area;
when the header sits at the tail of the IPv6 payload that read goes
past the payload.

After: the option is rejected with IPV6_EXTHDR_INVALID_OPTLEN, matching
how the IPv4 option loop already bounds a full option against the
remaining length. The check stays next to the read so each option type
does not need its own guard.

Ticket: #8817.
pull/15989/head
Uwez Khan 2 months ago committed by Victor Julien
parent dde0d7295b
commit 38b4ad79a3

@ -304,8 +304,10 @@ static void DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
/* length field for each opt */
uint8_t ip6_optlen = *(ptr + 1);
/* see if the optlen from the packet fits the total optslen */
if ((offset + 1 + ip6_optlen) > optslen) {
/* see if the optlen from the packet fits the total optslen.
* the option occupies 2 header bytes (type + len) plus
* ip6_optlen data bytes, so its data must end within optslen. */
if ((offset + 2 + ip6_optlen) > optslen) {
ENGINE_SET_INVALID_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
break;
}

Loading…
Cancel
Save