aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2007-04-24 17:58:30 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-24 17:58:30 -0400
commit0bcbc92629044b5403719f77fb015e9005b1f504 (patch)
treeac9635a8ac7b14edcaa0e5ad42a5bc70f778ec33
parent05d224468a273a9ee773a0e9d34227ee7f2c0840 (diff)
[IPV6]: Disallow RH0 by default.
A security issue is emerging. Disallow Routing Header Type 0 by default as we have been doing for IPv4. Note: We allow RH2 by default because it is harmless. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/ip-sysctl.txt9
-rw-r--r--include/linux/ipv6.h3
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--net/ipv6/addrconf.c11
-rw-r--r--net/ipv6/exthdrs.c40
5 files changed, 58 insertions, 6 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index d3aae1f9b4c1..702d1d8dd04a 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -851,6 +851,15 @@ accept_redirects - BOOLEAN
851 Functional default: enabled if local forwarding is disabled. 851 Functional default: enabled if local forwarding is disabled.
852 disabled if local forwarding is enabled. 852 disabled if local forwarding is enabled.
853 853
854accept_source_route - INTEGER
855 Accept source routing (routing extension header).
856
857 > 0: Accept routing header.
858 = 0: Accept only routing header type 2.
859 < 0: Do not accept routing header.
860
861 Default: 0
862
854autoconf - BOOLEAN 863autoconf - BOOLEAN
855 Autoconfigure addresses using Prefix Information in Router 864 Autoconfigure addresses using Prefix Information in Router
856 Advertisements. 865 Advertisements.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index f8241130f5ea..713eb5eaa81f 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -177,6 +177,7 @@ struct ipv6_devconf {
177#endif 177#endif
178#endif 178#endif
179 __s32 proxy_ndp; 179 __s32 proxy_ndp;
180 __s32 accept_source_route;
180 void *sysctl; 181 void *sysctl;
181}; 182};
182 183
@@ -205,6 +206,8 @@ enum {
205 DEVCONF_RTR_PROBE_INTERVAL, 206 DEVCONF_RTR_PROBE_INTERVAL,
206 DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, 207 DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
207 DEVCONF_PROXY_NDP, 208 DEVCONF_PROXY_NDP,
209 __DEVCONF_OPTIMISTIC_DAD,
210 DEVCONF_ACCEPT_SOURCE_ROUTE,
208 DEVCONF_MAX 211 DEVCONF_MAX
209}; 212};
210 213
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 2c5fb38d9392..9a8970bf99a6 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -580,6 +580,7 @@ enum {
580 NET_IPV6_RTR_PROBE_INTERVAL=21, 580 NET_IPV6_RTR_PROBE_INTERVAL=21,
581 NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, 581 NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
582 NET_IPV6_PROXY_NDP=23, 582 NET_IPV6_PROXY_NDP=23,
583 NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
583 __NET_IPV6_MAX 584 __NET_IPV6_MAX
584}; 585};
585 586
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7552663aa125..452a82ce4796 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -172,6 +172,7 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
172#endif 172#endif
173#endif 173#endif
174 .proxy_ndp = 0, 174 .proxy_ndp = 0,
175 .accept_source_route = 0, /* we do not accept RH0 by default. */
175}; 176};
176 177
177static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { 178static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -203,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
203#endif 204#endif
204#endif 205#endif
205 .proxy_ndp = 0, 206 .proxy_ndp = 0,
207 .accept_source_route = 0, /* we do not accept RH0 by default. */
206}; 208};
207 209
208/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 210/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -3356,6 +3358,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
3356#endif 3358#endif
3357#endif 3359#endif
3358 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; 3360 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
3361 array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
3359} 3362}
3360 3363
3361static inline size_t inet6_if_nlmsg_size(void) 3364static inline size_t inet6_if_nlmsg_size(void)
@@ -3884,6 +3887,14 @@ static struct addrconf_sysctl_table
3884 .proc_handler = &proc_dointvec, 3887 .proc_handler = &proc_dointvec,
3885 }, 3888 },
3886 { 3889 {
3890 .ctl_name = NET_IPV6_ACCEPT_SOURCE_ROUTE,
3891 .procname = "accept_source_route",
3892 .data = &ipv6_devconf.accept_source_route,
3893 .maxlen = sizeof(int),
3894 .mode = 0644,
3895 .proc_handler = &proc_dointvec,
3896 },
3897 {
3887 .ctl_name = 0, /* sentinel */ 3898 .ctl_name = 0, /* sentinel */
3888 } 3899 }
3889 }, 3900 },
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 28e0c6568272..6ed6a8cd6a68 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -362,10 +362,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
362 struct inet6_skb_parm *opt = IP6CB(skb); 362 struct inet6_skb_parm *opt = IP6CB(skb);
363 struct in6_addr *addr = NULL; 363 struct in6_addr *addr = NULL;
364 struct in6_addr daddr; 364 struct in6_addr daddr;
365 struct inet6_dev *idev;
365 int n, i; 366 int n, i;
366
367 struct ipv6_rt_hdr *hdr; 367 struct ipv6_rt_hdr *hdr;
368 struct rt0_hdr *rthdr; 368 struct rt0_hdr *rthdr;
369 int accept_source_route = ipv6_devconf.accept_source_route;
370
371 if (accept_source_route < 0 ||
372 ((idev = in6_dev_get(skb->dev)) == NULL)) {
373 kfree_skb(skb);
374 return -1;
375 }
376 if (idev->cnf.accept_source_route < 0) {
377 in6_dev_put(idev);
378 kfree_skb(skb);
379 return -1;
380 }
381
382 if (accept_source_route > idev->cnf.accept_source_route)
383 accept_source_route = idev->cnf.accept_source_route;
384
385 in6_dev_put(idev);
369 386
370 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 387 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
371 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 388 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
@@ -377,6 +394,22 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
377 394
378 hdr = (struct ipv6_rt_hdr *) skb->h.raw; 395 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
379 396
397 switch (hdr->type) {
398#ifdef CONFIG_IPV6_MIP6
399 break;
400#endif
401 case IPV6_SRCRT_TYPE_0:
402 if (accept_source_route <= 0)
403 break;
404 kfree_skb(skb);
405 return -1;
406 default:
407 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
408 IPSTATS_MIB_INHDRERRORS);
409 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
410 return -1;
411 }
412
380 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || 413 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
381 skb->pkt_type != PACKET_HOST) { 414 skb->pkt_type != PACKET_HOST) {
382 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 415 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -434,11 +467,6 @@ looped_back:
434 } 467 }
435 break; 468 break;
436#endif 469#endif
437 default:
438 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
439 IPSTATS_MIB_INHDRERRORS);
440 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
441 return -1;
442 } 470 }
443 471
444 /* 472 /*