Module Name: src Committed By: martin Date: Sat Jun 23 11:03:27 UTC 2018
Modified Files: src/sys/netinet6 [netbsd-8]: icmp6.c Log Message: Pull up following revision(s) (requested by maxv in ticket #893): sys/netinet6/icmp6.c: revision 1.228,1.230 Remove the RH0 code from ICMPv6. RH0 is deprecated by RFC5095 (2007) for security reasons. We already removed it in Route6. In addition there was an mbuf bug here: calling IP6_EXTHDR_GET twice with the same offset, but still using the pointer from the first call, which could have been made invalid. By luck, m_pulldown leaves zero-sized mbufs in place, instead of freeing them. And in general, using a 'finaldst' pointer on the mbuf, and then modifying that mbuf with IP6_EXTHDR_GET with a smaller offset, was really error- prone. Fix 'icmp6len', it shouldn't be ip6_plen, because we may not be at the beginning of the packet (off+ip6_plen is beyond the end of the mbuf). By luck, the IP6_EXTHDR_GET that follows will fail and prevent buffer overflows in non-jumbogram packets. For jumbograms we will probably be in trouble here; but it doesn't seem possible to craft reliably a jumbogram for a non-jumbogram-enabled device. So I don't think it's a huge problem. To generate a diff of this commit: cvs rdiff -u -r1.211.6.6 -r1.211.6.7 src/sys/netinet6/icmp6.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet6/icmp6.c diff -u src/sys/netinet6/icmp6.c:1.211.6.6 src/sys/netinet6/icmp6.c:1.211.6.7 --- src/sys/netinet6/icmp6.c:1.211.6.6 Fri Jun 8 10:14:33 2018 +++ src/sys/netinet6/icmp6.c Sat Jun 23 11:03:27 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: icmp6.c,v 1.211.6.6 2018/06/08 10:14:33 martin Exp $ */ +/* $NetBSD: icmp6.c,v 1.211.6.7 2018/06/23 11:03:27 martin Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.211.6.6 2018/06/08 10:14:33 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.211.6.7 2018/06/23 11:03:27 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -969,8 +969,6 @@ icmp6_notify_error(struct mbuf *m, int o int icmp6type = icmp6->icmp6_type; struct ip6_frag *fh; struct ip6_rthdr *rth; - struct ip6_rthdr0 *rth0; - int rthlen; struct ifnet *rcvif; int s; @@ -995,46 +993,15 @@ icmp6_notify_error(struct mbuf *m, int o nxt = eh->ip6e_nxt; break; case IPPROTO_ROUTING: - /* - * When the erroneous packet contains a - * routing header, we should examine the - * header to determine the final destination. - * Otherwise, we can't properly update - * information that depends on the final - * destination (e.g. path MTU). - */ + /* Ignore the option. */ IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, eoff, sizeof(*rth)); if (rth == NULL) { ICMP6_STATINC(ICMP6_STAT_TOOSHORT); return (-1); } - rthlen = (rth->ip6r_len + 1) << 3; - /* - * XXX: currently there is no - * officially defined type other - * than type-0. - * Note that if the segment left field - * is 0, all intermediate hops must - * have been passed. - */ - if (rth->ip6r_segleft && - rth->ip6r_type == IPV6_RTHDR_TYPE_0) { - int hops; - - IP6_EXTHDR_GET(rth0, - struct ip6_rthdr0 *, m, - eoff, rthlen); - if (rth0 == NULL) { - ICMP6_STATINC(ICMP6_STAT_TOOSHORT); - return (-1); - } - /* just ignore a bogus header */ - if ((rth0->ip6r0_len % 2) == 0 && - (hops = rth0->ip6r0_len/2)) - finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); - } - eoff += rthlen; + + eoff += (rth->ip6r_len + 1) << 3; nxt = rth->ip6r_nxt; break; case IPPROTO_FRAGMENT: @@ -2268,7 +2235,7 @@ icmp6_redirect_input(struct mbuf *m, int struct ifnet *ifp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_redirect *nd_rd; - int icmp6len = ntohs(ip6->ip6_plen); + int icmp6len = m->m_pkthdr.len - off; char *lladdr = NULL; int lladdrlen = 0; struct rtentry *rt = NULL;