diff options
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r-- | net/ipv6/af_inet6.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3b5669a2582..4252b3cc183 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -63,6 +63,20 @@ | |||
63 | #include <asm/system.h> | 63 | #include <asm/system.h> |
64 | #include <linux/mroute6.h> | 64 | #include <linux/mroute6.h> |
65 | 65 | ||
66 | #ifdef CONFIG_ANDROID_PARANOID_NETWORK | ||
67 | #include <linux/android_aid.h> | ||
68 | |||
69 | static inline int current_has_network(void) | ||
70 | { | ||
71 | return in_egroup_p(AID_INET) || capable(CAP_NET_RAW); | ||
72 | } | ||
73 | #else | ||
74 | static inline int current_has_network(void) | ||
75 | { | ||
76 | return 1; | ||
77 | } | ||
78 | #endif | ||
79 | |||
66 | MODULE_AUTHOR("Cast of dozens"); | 80 | MODULE_AUTHOR("Cast of dozens"); |
67 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); | 81 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); |
68 | MODULE_LICENSE("GPL"); | 82 | MODULE_LICENSE("GPL"); |
@@ -109,6 +123,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, | |||
109 | int try_loading_module = 0; | 123 | int try_loading_module = 0; |
110 | int err; | 124 | int err; |
111 | 125 | ||
126 | if (!current_has_network()) | ||
127 | return -EACCES; | ||
128 | |||
112 | if (sock->type != SOCK_RAW && | 129 | if (sock->type != SOCK_RAW && |
113 | sock->type != SOCK_DGRAM && | 130 | sock->type != SOCK_DGRAM && |
114 | !inet_ehash_secret) | 131 | !inet_ehash_secret) |
@@ -477,6 +494,21 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
477 | 494 | ||
478 | EXPORT_SYMBOL(inet6_getname); | 495 | EXPORT_SYMBOL(inet6_getname); |
479 | 496 | ||
497 | int inet6_killaddr_ioctl(struct net *net, void __user *arg) { | ||
498 | struct in6_ifreq ireq; | ||
499 | struct sockaddr_in6 sin6; | ||
500 | |||
501 | if (!capable(CAP_NET_ADMIN)) | ||
502 | return -EACCES; | ||
503 | |||
504 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) | ||
505 | return -EFAULT; | ||
506 | |||
507 | sin6.sin6_family = AF_INET6; | ||
508 | ipv6_addr_copy(&sin6.sin6_addr, &ireq.ifr6_addr); | ||
509 | return tcp_nuke_addr(net, (struct sockaddr *) &sin6); | ||
510 | } | ||
511 | |||
480 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 512 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
481 | { | 513 | { |
482 | struct sock *sk = sock->sk; | 514 | struct sock *sk = sock->sk; |
@@ -501,6 +533,8 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
501 | return addrconf_del_ifaddr(net, (void __user *) arg); | 533 | return addrconf_del_ifaddr(net, (void __user *) arg); |
502 | case SIOCSIFDSTADDR: | 534 | case SIOCSIFDSTADDR: |
503 | return addrconf_set_dstaddr(net, (void __user *) arg); | 535 | return addrconf_set_dstaddr(net, (void __user *) arg); |
536 | case SIOCKILLADDR: | ||
537 | return inet6_killaddr_ioctl(net, (void __user *) arg); | ||
504 | default: | 538 | default: |
505 | if (!sk->sk_prot->ioctl) | 539 | if (!sk->sk_prot->ioctl) |
506 | return -ENOIOCTLCMD; | 540 | return -ENOIOCTLCMD; |
@@ -875,6 +909,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
875 | skb_reset_transport_header(skb); | 909 | skb_reset_transport_header(skb); |
876 | __skb_push(skb, skb_gro_offset(skb)); | 910 | __skb_push(skb, skb_gro_offset(skb)); |
877 | 911 | ||
912 | ops = rcu_dereference(inet6_protos[proto]); | ||
878 | if (!ops || !ops->gro_receive) | 913 | if (!ops || !ops->gro_receive) |
879 | goto out_unlock; | 914 | goto out_unlock; |
880 | 915 | ||