Add a few checks to ip6_print() to make it stop decoding the IPv6
headers immediately when the header-specific functions signal an error
condition. Without this it tried to fetch the next header selector for
the next round regardless and could run outside of the allocated packet
space on a specially crafted IPv6 packet.
Brian Carpenter has demonstrated this for the Hop-by-Hop Options header.
Fix that specific case and also the Destination Options and Fragment
header processing as those use the same logic.
switch (nh) {
case IPPROTO_HOPOPTS:
advance = hbhopt_print(ndo, cp);
+ if (advance < 0)
+ return;
nh = *cp;
break;
case IPPROTO_DSTOPTS:
advance = dstopt_print(ndo, cp);
+ if (advance < 0)
+ return;
nh = *cp;
break;
case IPPROTO_FRAGMENT:
advance = frag6_print(ndo, cp, (const u_char *)ip6);
- if (ndo->ndo_snapend <= cp + advance)
+ if (advance < 0 || ndo->ndo_snapend <= cp + advance)
return;
nh = *cp;
fragmented = 1;
tftp-heapoverflow tftp-heapoverflow.pcap tftp-heapoverflow.out -t -v -n
relts-0x80000000 relts-0x80000000.pcap relts-0x80000000.out -t -v -n
+# bad packets from Brian Carpenter
+ipv6hdr-heapoverflow ipv6hdr-heapoverflow.pcap ipv6hdr-heapoverflow.out -t
+ipv6hdr-heapoverflow-v ipv6hdr-heapoverflow.pcap ipv6hdr-heapoverflow-v.out -t -v
+
# RTP tests
# fuzzed pcap
rtp-seg-fault-1 rtp-seg-fault-1.pcap rtp-seg-fault-1.out -t -v -T rtp
--- /dev/null
+IP6 (class 0x33, flowlabel 0x03030, hlim 48, next-header Options (0) payload length: 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [trunc] [|HBH]
--- /dev/null
+IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|HBH]