diff options
author | Guy Harris <guy@alum.mit.edu> | 2017-02-04 03:13:18 -0800 |
---|---|---|
committer | Denis Ovsienko <denis@ovsienko.info> | 2017-09-13 12:25:44 +0100 |
commit | 66df248b49095c261138b5a5e34d341a6bf9ac7f (patch) | |
tree | 0a3d2c754c3a71eb69dbbffe2baeddbcbd8024e9 /print-ip6.c | |
parent | 0318fa8b61bd6c837641129d585f1a73c652b1e0 (diff) | |
download | tcpdump-66df248b49095c261138b5a5e34d341a6bf9ac7f.tar.gz |
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).
Diffstat (limited to 'print-ip6.c')
-rw-r--r-- | print-ip6.c | 11 |
1 files changed, 11 insertions, 0 deletions
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; |