]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2017-12985/IPv6: Check for print routines returning -1 when running past the...
authorGuy Harris <[email protected]>
Sat, 4 Feb 2017 11:13:18 +0000 (03:13 -0800)
committerDenis Ovsienko <[email protected]>
Wed, 13 Sep 2017 11:25:44 +0000 (12:25 +0100)
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).

print-ip6.c
print-mobility.c
tests/TESTLIST
tests/ipv6-next-header-oobr-1.out [new file with mode: 0644]
tests/ipv6-next-header-oobr-1.pcap [new file with mode: 0644]
tests/ipv6-next-header-oobr-2.out [new file with mode: 0644]
tests/ipv6-next-header-oobr-2.pcap [new file with mode: 0644]

index 0075fcea2e51a389638bf48fbf33f73b72141fec..f2f56efb5459fdc2bd63db686afc2fba15d73144 100644 (file)
@@ -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;
index c7c03ee93a03c7f731c4811b336f587f637c5ab6..ca5541330ca981834352ab6b50cba95ad3d0f5a3 100644 (file)
@@ -332,5 +332,5 @@ mobility_print(netdissect_options *ndo,
 
  trunc:
        ND_PRINT((ndo, "%s", tstr));
-       return(mhlen);
+       return(-1);
 }
index c18586f6744911df4e2defe955605b183ae417e6..9b60df27b6b5cf8c1aabf6843058703b9803367a 100644 (file)
@@ -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 (file)
index 0000000..74eaf72
--- /dev/null
@@ -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 (file)
index 0000000..767350d
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 (file)
index 0000000..911d2ae
--- /dev/null
@@ -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 (file)
index 0000000..1be5729
Binary files /dev/null and b/tests/ipv6-next-header-oobr-2.pcap differ