defrag/ipv6: reject oversized reassembled payloads

Fragmented IPv6 packets with an unfragmentable extension header can
exceed the maximum allowed size. Use a u32 to check the size to prevent
wrap-around, rejecting the packet and setting an event if too large.

Ticket: #8818.
pull/16213/head
Jason Ish 3 months ago committed by Victor Julien
parent b06c134b5d
commit 94bb748e53

@ -490,17 +490,21 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
prev_offset = frag->offset; prev_offset = frag->offset;
} }
const uint32_t payload_len = (uint32_t)unfragmentable_len + fragmentable_len;
if (payload_len > IPV6_MAXPACKET) {
ENGINE_SET_EVENT(p, IPV6_FRAG_PKT_TOO_LARGE);
goto error_remove_tracker;
}
IPV6Hdr *ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + tracker->ip_hdr_offset); IPV6Hdr *ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + tracker->ip_hdr_offset);
DEBUG_VALIDATE_BUG_ON(unfragmentable_len > UINT16_MAX - fragmentable_len); ip6h->s_ip6_plen = htons((uint16_t)payload_len);
ip6h->s_ip6_plen = htons(fragmentable_len + unfragmentable_len);
/* if we have no unfragmentable part, so no ext hdrs before the frag /* if we have no unfragmentable part, so no ext hdrs before the frag
* header, we need to update the ipv6 headers next header field. This * header, we need to update the ipv6 headers next header field. This
* points to the frag header, and we will make it point to the layer * points to the frag header, and we will make it point to the layer
* directly after the frag header. */ * directly after the frag header. */
if (unfragmentable_len == 0) if (unfragmentable_len == 0)
ip6h->s_ip6_nxt = next_hdr; ip6h->s_ip6_nxt = next_hdr;
SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) + SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) + payload_len);
unfragmentable_len + fragmentable_len);
tracker->remove = 1; tracker->remove = 1;
DefragTrackerFreeFrags(tracker); DefragTrackerFreeFrags(tracker);

Loading…
Cancel
Save