diff options
| author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2007-04-24 17:58:30 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2007-04-24 17:58:30 -0400 |
| commit | 0bcbc92629044b5403719f77fb015e9005b1f504 (patch) | |
| tree | ac9635a8ac7b14edcaa0e5ad42a5bc70f778ec33 | |
| parent | 05d224468a273a9ee773a0e9d34227ee7f2c0840 (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.txt | 9 | ||||
| -rw-r--r-- | include/linux/ipv6.h | 3 | ||||
| -rw-r--r-- | include/linux/sysctl.h | 1 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 11 | ||||
| -rw-r--r-- | net/ipv6/exthdrs.c | 40 |
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 | ||
| 854 | accept_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 | |||
| 854 | autoconf - BOOLEAN | 863 | autoconf - 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 | ||
| 177 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | 178 | static 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 | ||
| 3361 | static inline size_t inet6_if_nlmsg_size(void) | 3364 | static 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 | /* |
