diff options
author | Brian Haley <brian.haley@hp.com> | 2008-11-13 01:59:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-13 01:59:21 -0500 |
commit | 6e093d9dfffc9a02cd54d36904c62f705f09900a (patch) | |
tree | b9250d24821ffa8edb55fee50e0d695afd23a6f9 /net | |
parent | b2af2c1d3e4ddeea9d02c46d0df0c322cc7b7061 (diff) |
ipv6: routing header fixes
This patch fixes two bugs:
1. setsockopt() of anything but a Type 2 routing header should return
EINVAL instead of EPERM. Noticed by Shan Wei
(shanwei@cn.fujitsu.com).
2. setsockopt()/sendmsg() of a Type 2 routing header with invalid
length or segments should return EINVAL. These values are statically
fixed in RFC 3775, unlike the variable Type 0 was.
Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/datagram.c | 5 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 5 |
2 files changed, 10 insertions, 0 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 410046a8cc91..e44deb8d4df2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -661,6 +661,11 @@ int datagram_send_ctl(struct net *net, | |||
661 | switch (rthdr->type) { | 661 | switch (rthdr->type) { |
662 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 662 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
663 | case IPV6_SRCRT_TYPE_2: | 663 | case IPV6_SRCRT_TYPE_2: |
664 | if (rthdr->hdrlen != 2 || | ||
665 | rthdr->segments_left != 1) { | ||
666 | err = -EINVAL; | ||
667 | goto exit_f; | ||
668 | } | ||
664 | break; | 669 | break; |
665 | #endif | 670 | #endif |
666 | default: | 671 | default: |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 4e5eac301f91..2aa294be0c79 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -366,11 +366,16 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
366 | } | 366 | } |
367 | 367 | ||
368 | /* routing header option needs extra check */ | 368 | /* routing header option needs extra check */ |
369 | retv = -EINVAL; | ||
369 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { | 370 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { |
370 | struct ipv6_rt_hdr *rthdr = opt->srcrt; | 371 | struct ipv6_rt_hdr *rthdr = opt->srcrt; |
371 | switch (rthdr->type) { | 372 | switch (rthdr->type) { |
372 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 373 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
373 | case IPV6_SRCRT_TYPE_2: | 374 | case IPV6_SRCRT_TYPE_2: |
375 | if (rthdr->hdrlen != 2 || | ||
376 | rthdr->segments_left != 1) | ||
377 | goto sticky_done; | ||
378 | |||
374 | break; | 379 | break; |
375 | #endif | 380 | #endif |
376 | default: | 381 | default: |