aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/af_inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r--net/ipv6/af_inet6.c35
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
69static inline int current_has_network(void)
70{
71 return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
72}
73#else
74static inline int current_has_network(void)
75{
76 return 1;
77}
78#endif
79
66MODULE_AUTHOR("Cast of dozens"); 80MODULE_AUTHOR("Cast of dozens");
67MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); 81MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
68MODULE_LICENSE("GPL"); 82MODULE_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
478EXPORT_SYMBOL(inet6_getname); 495EXPORT_SYMBOL(inet6_getname);
479 496
497int 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
480int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 512int 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