From: Guy Harris Date: Sat, 4 Feb 2017 11:13:18 +0000 (-0800) Subject: CVE-2017-12985/IPv6: Check for print routines returning -1 when running past the... X-Git-Tag: tcpdump-4.99-bp~1974 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/66df248b49095c261138b5a5e34d341a6bf9ac7f CVE-2017-12985/IPv6: Check for print routines returning -1 when running past the end. rt6_print(), ah_print(), and esp_print() return -1 if they run up against the end of the packet while dissecting; if that happens, stop dissecting, don't try to fetch the next header value, because 1) *it* might be past the end of the packet and 2) we won't be using it in any case, as we'll be exiting the loop. Also, change mobility_print() to return -1 if it runs up against the end of the packet, and stop dissecting if it does so. This fixes a buffer over-read discovered by Brian 'geeknik' Carpenter. Add tests using the capture files supplied by the reporter(s). --- diff --git a/print-ip6.c b/print-ip6.c index 0075fcea..f2f56efb 100644 --- a/print-ip6.c +++ b/print-ip6.c @@ -280,6 +280,8 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) advance = sizeof(struct ip6_hdr); nh = ip6->ip6_nxt; while (cp < ndo->ndo_snapend && advance > 0) { + if (len < (u_int)advance) + goto trunc; cp += advance; len -= advance; @@ -322,10 +324,15 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) * mobility header. */ advance = mobility_print(ndo, cp, (const u_char *)ip6); + if (advance < 0) + return; nh = *cp; return; case IPPROTO_ROUTING: + ND_TCHECK(*cp); advance = rt6_print(ndo, cp, (const u_char *)ip6); + if (advance < 0) + return; nh = *cp; break; case IPPROTO_SCTP: @@ -345,12 +352,16 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) return; case IPPROTO_AH: advance = ah_print(ndo, cp); + if (advance < 0) + return; nh = *cp; break; case IPPROTO_ESP: { int enh, padlen; advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen); + if (advance < 0) + return; nh = enh & 0xff; len -= padlen; break; diff --git a/print-mobility.c b/print-mobility.c index c7c03ee9..ca554133 100644 --- a/print-mobility.c +++ b/print-mobility.c @@ -332,5 +332,5 @@ mobility_print(netdissect_options *ndo, trunc: ND_PRINT((ndo, "%s", tstr)); - return(mhlen); + return(-1); } diff --git a/tests/TESTLIST b/tests/TESTLIST index c18586f6..9b60df27 100644 --- a/tests/TESTLIST +++ b/tests/TESTLIST @@ -432,6 +432,8 @@ otv-heapoverflow-1 otv-heapoverflow-1.pcap otv-heapoverflow-1.out -c10 otv-heapoverflow-2 otv-heapoverflow-2.pcap otv-heapoverflow-2.out -c10 q933-heapoverflow-2 q933-heapoverflow-2.pcap q933-heapoverflow-2.out atm-heapoverflow atm-heapoverflow.pcap atm-heapoverflow.out -c1 -e +ipv6-next-header-oobr-1 ipv6-next-header-oobr-1.pcap ipv6-next-header-oobr-1.out +ipv6-next-header-oobr-2 ipv6-next-header-oobr-2.pcap ipv6-next-header-oobr-2.out # bad packets from Kamil Frankowicz snmp-heapoverflow-1 snmp-heapoverflow-1.pcap snmp-heapoverflow-1.out diff --git a/tests/ipv6-next-header-oobr-1.out b/tests/ipv6-next-header-oobr-1.out new file mode 100644 index 00000000..74eaf72c --- /dev/null +++ b/tests/ipv6-next-header-oobr-1.out @@ -0,0 +1 @@ +IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|ip6] diff --git a/tests/ipv6-next-header-oobr-1.pcap b/tests/ipv6-next-header-oobr-1.pcap new file mode 100644 index 00000000..767350d9 Binary files /dev/null and b/tests/ipv6-next-header-oobr-1.pcap differ diff --git a/tests/ipv6-next-header-oobr-2.out b/tests/ipv6-next-header-oobr-2.out new file mode 100644 index 00000000..911d2ae2 --- /dev/null +++ b/tests/ipv6-next-header-oobr-2.out @@ -0,0 +1 @@ +IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|AH] diff --git a/tests/ipv6-next-header-oobr-2.pcap b/tests/ipv6-next-header-oobr-2.pcap new file mode 100644 index 00000000..1be5729b Binary files /dev/null and b/tests/ipv6-next-header-oobr-2.pcap differ