diff options
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 26b83e512a09..c042ce19bd14 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -67,7 +67,7 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
| 67 | 67 | ||
| 68 | /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ | 68 | /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ |
| 69 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) | 69 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) |
| 70 | return -EINVAL; | 70 | return -ENOPROTOOPT; |
| 71 | 71 | ||
| 72 | new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; | 72 | new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; |
| 73 | 73 | ||
| @@ -446,7 +446,7 @@ done: | |||
| 446 | 446 | ||
| 447 | case IPV6_MULTICAST_HOPS: | 447 | case IPV6_MULTICAST_HOPS: |
| 448 | if (sk->sk_type == SOCK_STREAM) | 448 | if (sk->sk_type == SOCK_STREAM) |
| 449 | goto e_inval; | 449 | break; |
| 450 | if (optlen < sizeof(int)) | 450 | if (optlen < sizeof(int)) |
| 451 | goto e_inval; | 451 | goto e_inval; |
| 452 | if (val > 255 || val < -1) | 452 | if (val > 255 || val < -1) |
| @@ -458,13 +458,15 @@ done: | |||
| 458 | case IPV6_MULTICAST_LOOP: | 458 | case IPV6_MULTICAST_LOOP: |
| 459 | if (optlen < sizeof(int)) | 459 | if (optlen < sizeof(int)) |
| 460 | goto e_inval; | 460 | goto e_inval; |
| 461 | if (val != valbool) | ||
| 462 | goto e_inval; | ||
| 461 | np->mc_loop = valbool; | 463 | np->mc_loop = valbool; |
| 462 | retv = 0; | 464 | retv = 0; |
| 463 | break; | 465 | break; |
| 464 | 466 | ||
| 465 | case IPV6_MULTICAST_IF: | 467 | case IPV6_MULTICAST_IF: |
| 466 | if (sk->sk_type == SOCK_STREAM) | 468 | if (sk->sk_type == SOCK_STREAM) |
| 467 | goto e_inval; | 469 | break; |
| 468 | if (optlen < sizeof(int)) | 470 | if (optlen < sizeof(int)) |
| 469 | goto e_inval; | 471 | goto e_inval; |
| 470 | 472 | ||
| @@ -860,7 +862,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 860 | if (sk->sk_protocol != IPPROTO_UDP && | 862 | if (sk->sk_protocol != IPPROTO_UDP && |
| 861 | sk->sk_protocol != IPPROTO_UDPLITE && | 863 | sk->sk_protocol != IPPROTO_UDPLITE && |
| 862 | sk->sk_protocol != IPPROTO_TCP) | 864 | sk->sk_protocol != IPPROTO_TCP) |
| 863 | return -EINVAL; | 865 | return -ENOPROTOOPT; |
| 864 | if (sk->sk_state != TCP_ESTABLISHED) | 866 | if (sk->sk_state != TCP_ESTABLISHED) |
| 865 | return -ENOTCONN; | 867 | return -ENOTCONN; |
| 866 | val = sk->sk_family; | 868 | val = sk->sk_family; |
| @@ -874,6 +876,8 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 874 | return -EINVAL; | 876 | return -EINVAL; |
| 875 | if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) | 877 | if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) |
| 876 | return -EFAULT; | 878 | return -EFAULT; |
| 879 | if (gsf.gf_group.ss_family != AF_INET6) | ||
| 880 | return -EADDRNOTAVAIL; | ||
| 877 | lock_sock(sk); | 881 | lock_sock(sk); |
| 878 | err = ip6_mc_msfget(sk, &gsf, | 882 | err = ip6_mc_msfget(sk, &gsf, |
| 879 | (struct group_filter __user *)optval, optlen); | 883 | (struct group_filter __user *)optval, optlen); |
