Skip to content

Commit

Permalink
[IPV6]: Restore semantics of Routing Header processing.
Browse files Browse the repository at this point in the history
The "fix" for emerging security threat was overkill and it broke
basic semantic of IPv6 routing header processing.  We should assume
RT0 (or even RT2, depends on configuration) as "unknown" RH type so
that we
- silently ignore the routing header if segleft == 0
- send ICMPv6 Parameter Problem message back to the sender,
  otherwise.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
YOSHIFUJI Hideaki authored and David S. Miller committed Jul 11, 2007
1 parent c9726d6 commit c382bb9
Showing 1 changed file with 16 additions and 31 deletions.
47 changes: 16 additions & 31 deletions net/ipv6/exthdrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,22 +372,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_transport_offset(skb) + 8) ||
!pskb_may_pull(skb, (skb_transport_offset(skb) +
((skb_transport_header(skb)[1] + 1) << 3)))) {
Expand All @@ -399,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)

hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);

switch (hdr->type) {
#ifdef CONFIG_IPV6_MIP6
case IPV6_SRCRT_TYPE_2:
break;
#endif
case IPV6_SRCRT_TYPE_0:
if (accept_source_route > 0)
break;
kfree_skb(skb);
return -1;
default:
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
(&hdr->type) - skb_network_header(skb));
return -1;
}

if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
skb->pkt_type != PACKET_HOST) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
Expand Down Expand Up @@ -455,6 +428,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)

switch (hdr->type) {
case IPV6_SRCRT_TYPE_0:
if (accept_source_route <= 0)
goto unknown_rh;
if (hdr->hdrlen & 0x01) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
IPSTATS_MIB_INHDRERRORS);
Expand All @@ -466,6 +441,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
break;
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
if (accept_source_route < 0)
goto unknown_rh;
/* Silently discard invalid RTH type 2 */
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
Expand All @@ -475,6 +452,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
}
break;
#endif
default:
goto unknown_rh;
}

/*
Expand Down Expand Up @@ -578,6 +557,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
skb_push(skb, skb->data - skb_network_header(skb));
dst_input(skb);
return -1;

unknown_rh:
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
(&hdr->type) - skb_network_header(skb));
return -1;
}

static struct inet6_protocol rthdr_protocol = {
Expand Down

0 comments on commit c382bb9

Please sign in to comment.