The "fix" for emerging security threats was overkill and it broke basic semantic of IPv6 routing header processing. We should assume RT0 as "unknown" RH type so that we - silently ignore the routing header if segleft == 0 - or, send ICMPv6 Parameter Problem message back to the sender, otherwise.
Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> --- Documentation/networking/ip-sysctl.txt | 5 +-- net/ipv6/exthdrs.c | 38 +++++++++++--------------------- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index d512f22..0d33275 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -726,9 +726,8 @@ accept_redirects - BOOLEAN accept_source_route - INTEGER Accept source routing (routing extension header). - > 0: Accept routing header. - = 0: Accept only routing header type 2. - < 0: Do not accept routing header. + > 0: Accept Routing Header Type 0. + <= 0: Do not accept Routing Header. Default: 0 diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index a7cac22..b3d9adf 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -227,22 +227,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) struct rt0_hdr *rthdr; int accept_source_route = ipv6_devconf.accept_source_route; - if (accept_source_route < 0 || - ((idev = in6_dev_get(skb->dev)) == NULL)) { - kfree_skb(skb); - return -1; - } - if (idev->cnf.accept_source_route < 0) { + idev = in6_dev_get(skb->dev); + if (idev) { + if (accept_source_route > idev->cnf.accept_source_route) + accept_source_route = idev->cnf.accept_source_route; in6_dev_put(idev); - kfree_skb(skb); - return -1; } - if (accept_source_route > idev->cnf.accept_source_route) - accept_source_route = idev->cnf.accept_source_route; - - in6_dev_put(idev); - if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); @@ -252,18 +243,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) hdr = (struct ipv6_rt_hdr *) skb->h.raw; - switch (hdr->type) { - case IPV6_SRCRT_TYPE_0: - if (accept_source_route > 0) - break; - kfree_skb(skb); - return -1; - default: - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); - return -1; - } - if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || skb->pkt_type != PACKET_HOST) { IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); @@ -282,6 +261,10 @@ looped_back: return 1; } + if (hdr->type != IPV6_SRCRT_TYPE_0 || + accept_source_route <= 0) + goto unknown_rh; + if (hdr->hdrlen & 0x01) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); @@ -359,6 +342,11 @@ looped_back: skb_push(skb, skb->data - skb->nh.raw); dst_input(skb); return -1; + +unknown_rh: + IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); + return -1; } static struct inet6_protocol rthdr_protocol = { -- 1.5.1 -- YOSHIFUJI Hideaki @ USAGI Project <[EMAIL PROTECTED]> GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html