提交 c382bb9d 编写于 作者: Y YOSHIFUJI Hideaki 提交者: David S. Miller

[IPV6]: Restore semantics of Routing Header processing.

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: NYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 c9726d68
...@@ -372,21 +372,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -372,21 +372,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
struct rt0_hdr *rthdr; struct rt0_hdr *rthdr;
int accept_source_route = ipv6_devconf.accept_source_route; int accept_source_route = ipv6_devconf.accept_source_route;
if (accept_source_route < 0 || idev = in6_dev_get(skb->dev);
((idev = in6_dev_get(skb->dev)) == NULL)) { if (idev) {
kfree_skb(skb);
return -1;
}
if (idev->cnf.accept_source_route < 0) {
in6_dev_put(idev);
kfree_skb(skb);
return -1;
}
if (accept_source_route > idev->cnf.accept_source_route) if (accept_source_route > idev->cnf.accept_source_route)
accept_source_route = idev->cnf.accept_source_route; accept_source_route = idev->cnf.accept_source_route;
in6_dev_put(idev); in6_dev_put(idev);
}
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
!pskb_may_pull(skb, (skb_transport_offset(skb) + !pskb_may_pull(skb, (skb_transport_offset(skb) +
...@@ -399,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -399,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); 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) || if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
skb->pkt_type != PACKET_HOST) { skb->pkt_type != PACKET_HOST) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
...@@ -455,6 +428,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -455,6 +428,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
switch (hdr->type) { switch (hdr->type) {
case IPV6_SRCRT_TYPE_0: case IPV6_SRCRT_TYPE_0:
if (accept_source_route <= 0)
goto unknown_rh;
if (hdr->hdrlen & 0x01) { if (hdr->hdrlen & 0x01) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
IPSTATS_MIB_INHDRERRORS); IPSTATS_MIB_INHDRERRORS);
...@@ -466,6 +441,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -466,6 +441,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
break; break;
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2: case IPV6_SRCRT_TYPE_2:
if (accept_source_route < 0)
goto unknown_rh;
/* Silently discard invalid RTH type 2 */ /* Silently discard invalid RTH type 2 */
if (hdr->hdrlen != 2 || hdr->segments_left != 1) { if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
...@@ -475,6 +452,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -475,6 +452,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
} }
break; break;
#endif #endif
default:
goto unknown_rh;
} }
/* /*
...@@ -578,6 +557,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -578,6 +557,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
skb_push(skb, skb->data - skb_network_header(skb)); skb_push(skb, skb->data - skb_network_header(skb));
dst_input(skb); dst_input(skb);
return -1; 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 = { static struct inet6_protocol rthdr_protocol = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册