数年ぶりの投稿の野沢と申します。 FreeBSD-SA-07:03.ipv6 の patch だけでは十分ではないと itojun さんから聞き、 私が使用している 6.2-RELEASE-p4 で patch を作りました。 #たまには貢献できればと思いまして (^^)
元は http://www.kame.net/newsletter/20070502/index.ja.html です。 current では、どうなっているかご存知な方いらっしゃいますか? #んー、今になって route6.c の "@@ -89,6 +91,22 @@" の部分が気になってきた (^^;
--- sys/netinet6/in6_proto.c.orig Fri May 4 15:14:10 2007 +++ sys/netinet6/in6_proto.c Fri May 18 13:52:14 2007 @@ -361,7 +361,7 @@ int ip6_maxfragpackets; /* initialized in frag6.c:frag6_init() */ int ip6_maxfrags; /* initialized in frag6.c:frag6_init() */ int ip6_log_interval = 5; -int ip6_hdrnestlimit = 50; /* appropriate? */ +int ip6_hdrnestlimit = 15; /* appropriate? */ int ip6_dad_count = 1; /* DupAddrDetectionTransmits */ int ip6_auto_flowlabel = 1; int ip6_gif_hlim = 0; --- sys/netinet6/ip6_input.c.orig Wed Feb 1 01:36:11 2006 +++ sys/netinet6/ip6_input.c Mon May 21 10:30:14 2007 @@ -234,7 +234,7 @@ int off = sizeof(struct ip6_hdr), nest; u_int32_t plen; u_int32_t rtalert = ~0; - int nxt, ours = 0; + int nxt, ours = 0, rh_present = 0; struct ifnet *deliverifp = NULL; struct in6_addr odst; int srcrt = 0; @@ -758,9 +758,11 @@ in6_ifstat_inc(deliverifp, ifs6_in_deliver); nest = 0; + rh_present = 0; while (nxt != IPPROTO_DONE) { if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { ip6stat.ip6s_toomanyhdr++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); goto bad; } @@ -774,6 +776,30 @@ goto bad; } + /* + * Here we try to reject packets with more than 1 routing + * headers. we do this here (instead of tagging mbuf route6.c) + * for the sake of computational costs, such as malloc(). + * + * The code could be too restrictive - there could be + * actual use of more than 1 routing headers on a packet + * which cannot be used to do bad things unlike + * IPV6_RTHDR_TYPE_0. This code could also prohibit a mixed use + * of TYPE_x and TYPE_y routing headers (x != y) even if it is + * safe. + * + * We may need to revisit this behavior if and when a new type + * of routing header is defined. + */ + if (nxt == IPPROTO_ROUTING) { + if (rh_present++) { + in6_ifstat_inc(m->m_pkthdr.rcvif, + ifs6_in_hdrerr); + ip6stat.ip6s_badoptions++; + goto bad; + } + } + #ifdef IPSEC /* * enforce IPsec policy checking if we are seeing last header. --- sys/netinet6/route6.c.orig Fri May 4 15:14:10 2007 +++ sys/netinet6/route6.c Mon May 21 10:40:12 2007 @@ -51,8 +51,10 @@ extern int ip6_rthdr0_allowed; +#if 0 static int ip6_rthdr0 __P((struct mbuf *, struct ip6_hdr *, struct ip6_rthdr0 *)); +#endif int route6_input(mp, offp, proto) @@ -89,6 +91,22 @@ #endif switch (rh->ip6r_type) { +#if 0 + /* + * See http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf + * for why IPV6_RTHDR_TYPE_0 is banned here. + * + * We return ICMPv6 parameter problem so that innocent people + * (not an attacker) would notice about the use of IPV6_RTHDR_TYPE_0. + * Since there's no amplification, and ICMPv6 error will be rate- + * controlled, it shouldn't cause any problem. + * If you are concerned about this, you may want to use the following + * code fragment: + * + * case IPV6_RTHDR_TYPE_0: + * m_freem(m); + * return (IPPROTO_DONE); + */ case IPV6_RTHDR_TYPE_0: if (!ip6_rthdr0_allowed) return (IPPROTO_DONE); @@ -118,6 +136,7 @@ if (ip6_rthdr0(m, ip6, (struct ip6_rthdr0 *)rh)) return (IPPROTO_DONE); break; +#endif default: /* unknown routing type */ if (rh->ip6r_segleft == 0) { @@ -134,6 +153,7 @@ return (rh->ip6r_nxt); } +#if 0 /* * Type0 routing header processing * @@ -237,3 +257,4 @@ m_freem(m); return (-1); } +#endif