aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-11-15 22:03:06 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-18 20:32:45 -0500
commitaf31f412c7c7a3c0fda4bf4beaf0c85af1f263c8 (patch)
treef140b9a4956d891c1e5cf59c30c65cc7245cc764 /net/ipv6
parent52e804c6dfaa5df1e4b0e290357b82ad4e4cda2c (diff)
net: Allow userns root to control ipv6
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls. Settings that merely control a single network device are allowed. Either the network device is a logical network device where restrictions make no difference or the network device is hardware NIC that has been explicity moved from the initial network namespace. In general policy and network stack state changes are allowed while resource control is left unchanged. Allow the SIOCSIFADDR ioctl to add ipv6 addresses. Allow the SIOCDIFADDR ioctl to delete ipv6 addresses. Allow the SIOCADDRT ioctl to add ipv6 routes. Allow the SIOCDELRT ioctl to delete ipv6 routes. Allow creation of ipv6 raw sockets. Allow setting the IPV6_JOIN_ANYCAST socket option. Allow setting the IPV6_FL_A_RENEW parameter of the IPV6_FLOWLABEL_MGR socket option. Allow setting the IPV6_TRANSPARENT socket option. Allow setting the IPV6_HOPOPTS socket option. Allow setting the IPV6_RTHDRDSTOPTS socket option. Allow setting the IPV6_DSTOPTS socket option. Allow setting the IPV6_IPSEC_POLICY socket option. Allow setting the IPV6_XFRM_POLICY socket option. Allow sending packets with the IPV6_2292HOPOPTS control message. Allow sending packets with the IPV6_2292DSTOPTS control message. Allow sending packets with the IPV6_RTHDRDSTOPTS control message. Allow setting the multicast routing socket options on non multicast routing sockets. Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL, and SIOCDELTUNNEL ioctls for setting up, changing and deleting tunnels over ipv6. Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL, SIOCDELTUNNEL ioctls for setting up, changing and deleting ipv6 over ipv4 tunnels. Allow the SIOCADDPRL, SIOCDELPRL, SIOCCHGPRL ioctls for adding, deleting, and changing the potential router list for ISATAP tunnels. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/anycast.c2
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/ip6_flowlabel.c3
-rw-r--r--net/ipv6/ip6_gre.c4
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ip6mr.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c7
-rw-r--r--net/ipv6/netfilter/ip6_tables.c8
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/sit.c8
12 files changed, 28 insertions, 25 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e21bdb92565d..67ac9f8d1976 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2413,7 +2413,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
2413 struct in6_ifreq ireq; 2413 struct in6_ifreq ireq;
2414 int err; 2414 int err;
2415 2415
2416 if (!capable(CAP_NET_ADMIN)) 2416 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2417 return -EPERM; 2417 return -EPERM;
2418 2418
2419 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) 2419 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -2432,7 +2432,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
2432 struct in6_ifreq ireq; 2432 struct in6_ifreq ireq;
2433 int err; 2433 int err;
2434 2434
2435 if (!capable(CAP_NET_ADMIN)) 2435 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2436 return -EPERM; 2436 return -EPERM;
2437 2437
2438 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) 2438 if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 7bafc51cda11..4b29f6b52c11 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -160,7 +160,8 @@ lookup_protocol:
160 } 160 }
161 161
162 err = -EPERM; 162 err = -EPERM;
163 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) 163 if (sock->type == SOCK_RAW && !kern &&
164 !ns_capable(net->user_ns, CAP_NET_RAW))
164 goto out_rcu_unlock; 165 goto out_rcu_unlock;
165 166
166 sock->ops = answer->ops; 167 sock->ops = answer->ops;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 4963c769a13f..2f4f584d796d 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -64,7 +64,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
64 int ishost = !net->ipv6.devconf_all->forwarding; 64 int ishost = !net->ipv6.devconf_all->forwarding;
65 int err = 0; 65 int err = 0;
66 66
67 if (!capable(CAP_NET_ADMIN)) 67 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
68 return -EPERM; 68 return -EPERM;
69 if (ipv6_addr_is_multicast(addr)) 69 if (ipv6_addr_is_multicast(addr))
70 return -EINVAL; 70 return -EINVAL;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 93cbad2c0aa7..8edf2601065a 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -701,7 +701,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
701 err = -EINVAL; 701 err = -EINVAL;
702 goto exit_f; 702 goto exit_f;
703 } 703 }
704 if (!capable(CAP_NET_RAW)) { 704 if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
705 err = -EPERM; 705 err = -EPERM;
706 goto exit_f; 706 goto exit_f;
707 } 707 }
@@ -721,7 +721,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
721 err = -EINVAL; 721 err = -EINVAL;
722 goto exit_f; 722 goto exit_f;
723 } 723 }
724 if (!capable(CAP_NET_RAW)) { 724 if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
725 err = -EPERM; 725 err = -EPERM;
726 goto exit_f; 726 goto exit_f;
727 } 727 }
@@ -746,7 +746,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
746 err = -EINVAL; 746 err = -EINVAL;
747 goto exit_f; 747 goto exit_f;
748 } 748 }
749 if (!capable(CAP_NET_RAW)) { 749 if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
750 err = -EPERM; 750 err = -EPERM;
751 goto exit_f; 751 goto exit_f;
752 } 752 }
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 90bbefb57943..29124b7a04c8 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -519,7 +519,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
519 } 519 }
520 read_unlock_bh(&ip6_sk_fl_lock); 520 read_unlock_bh(&ip6_sk_fl_lock);
521 521
522 if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { 522 if (freq.flr_share == IPV6_FL_S_NONE &&
523 ns_capable(net->user_ns, CAP_NET_ADMIN)) {
523 fl = fl_lookup(net, freq.flr_label); 524 fl = fl_lookup(net, freq.flr_label);
524 if (fl) { 525 if (fl) {
525 err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); 526 err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 823fd64d0136..867466c96aac 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1146,7 +1146,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
1146 case SIOCADDTUNNEL: 1146 case SIOCADDTUNNEL:
1147 case SIOCCHGTUNNEL: 1147 case SIOCCHGTUNNEL:
1148 err = -EPERM; 1148 err = -EPERM;
1149 if (!capable(CAP_NET_ADMIN)) 1149 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1150 goto done; 1150 goto done;
1151 1151
1152 err = -EFAULT; 1152 err = -EFAULT;
@@ -1194,7 +1194,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
1194 1194
1195 case SIOCDELTUNNEL: 1195 case SIOCDELTUNNEL:
1196 err = -EPERM; 1196 err = -EPERM;
1197 if (!capable(CAP_NET_ADMIN)) 1197 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1198 goto done; 1198 goto done;
1199 1199
1200 if (dev == ign->fb_tunnel_dev) { 1200 if (dev == ign->fb_tunnel_dev) {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index bf3a549267d3..fb828e9fe8e0 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1350,7 +1350,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1350 case SIOCADDTUNNEL: 1350 case SIOCADDTUNNEL:
1351 case SIOCCHGTUNNEL: 1351 case SIOCCHGTUNNEL:
1352 err = -EPERM; 1352 err = -EPERM;
1353 if (!capable(CAP_NET_ADMIN)) 1353 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1354 break; 1354 break;
1355 err = -EFAULT; 1355 err = -EFAULT;
1356 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) 1356 if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
@@ -1383,7 +1383,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1383 break; 1383 break;
1384 case SIOCDELTUNNEL: 1384 case SIOCDELTUNNEL:
1385 err = -EPERM; 1385 err = -EPERM;
1386 if (!capable(CAP_NET_ADMIN)) 1386 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1387 break; 1387 break;
1388 1388
1389 if (dev == ip6n->fb_tnl_dev) { 1389 if (dev == ip6n->fb_tnl_dev) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index f7c7c6319720..d7330f8ea6d4 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1583,7 +1583,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
1583 return -ENOENT; 1583 return -ENOENT;
1584 1584
1585 if (optname != MRT6_INIT) { 1585 if (optname != MRT6_INIT) {
1586 if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN)) 1586 if (sk != mrt->mroute6_sk && !ns_capable(net->user_ns, CAP_NET_ADMIN))
1587 return -EACCES; 1587 return -EACCES;
1588 } 1588 }
1589 1589
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4b4172dbbe64..ee94d31c9d4d 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -343,7 +343,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
343 break; 343 break;
344 344
345 case IPV6_TRANSPARENT: 345 case IPV6_TRANSPARENT:
346 if (valbool && !capable(CAP_NET_ADMIN) && !capable(CAP_NET_RAW)) { 346 if (valbool && !ns_capable(net->user_ns, CAP_NET_ADMIN) &&
347 !ns_capable(net->user_ns, CAP_NET_RAW)) {
347 retv = -EPERM; 348 retv = -EPERM;
348 break; 349 break;
349 } 350 }
@@ -381,7 +382,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
381 382
382 /* hop-by-hop / destination options are privileged option */ 383 /* hop-by-hop / destination options are privileged option */
383 retv = -EPERM; 384 retv = -EPERM;
384 if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) 385 if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
385 break; 386 break;
386 387
387 opt = ipv6_renew_options(sk, np->opt, optname, 388 opt = ipv6_renew_options(sk, np->opt, optname,
@@ -754,7 +755,7 @@ done:
754 case IPV6_IPSEC_POLICY: 755 case IPV6_IPSEC_POLICY:
755 case IPV6_XFRM_POLICY: 756 case IPV6_XFRM_POLICY:
756 retv = -EPERM; 757 retv = -EPERM;
757 if (!capable(CAP_NET_ADMIN)) 758 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
758 break; 759 break;
759 retv = xfrm_user_policy(sk, optname, optval, optlen); 760 retv = xfrm_user_policy(sk, optname, optval, optlen);
760 break; 761 break;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 10ce76a2cb94..74cadd0719a5 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1854,7 +1854,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
1854{ 1854{
1855 int ret; 1855 int ret;
1856 1856
1857 if (!capable(CAP_NET_ADMIN)) 1857 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1858 return -EPERM; 1858 return -EPERM;
1859 1859
1860 switch (cmd) { 1860 switch (cmd) {
@@ -1969,7 +1969,7 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1969{ 1969{
1970 int ret; 1970 int ret;
1971 1971
1972 if (!capable(CAP_NET_ADMIN)) 1972 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1973 return -EPERM; 1973 return -EPERM;
1974 1974
1975 switch (cmd) { 1975 switch (cmd) {
@@ -1991,7 +1991,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1991{ 1991{
1992 int ret; 1992 int ret;
1993 1993
1994 if (!capable(CAP_NET_ADMIN)) 1994 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1995 return -EPERM; 1995 return -EPERM;
1996 1996
1997 switch (cmd) { 1997 switch (cmd) {
@@ -2016,7 +2016,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2016{ 2016{
2017 int ret; 2017 int ret;
2018 2018
2019 if (!capable(CAP_NET_ADMIN)) 2019 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
2020 return -EPERM; 2020 return -EPERM;
2021 2021
2022 switch (cmd) { 2022 switch (cmd) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c6215e2b9d7f..a86b65599328 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2036,7 +2036,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
2036 switch(cmd) { 2036 switch(cmd) {
2037 case SIOCADDRT: /* Add a route */ 2037 case SIOCADDRT: /* Add a route */
2038 case SIOCDELRT: /* Delete a route */ 2038 case SIOCDELRT: /* Delete a route */
2039 if (!capable(CAP_NET_ADMIN)) 2039 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2040 return -EPERM; 2040 return -EPERM;
2041 err = copy_from_user(&rtmsg, arg, 2041 err = copy_from_user(&rtmsg, arg,
2042 sizeof(struct in6_rtmsg)); 2042 sizeof(struct in6_rtmsg));
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index ca6c2c8e71d2..fee21c6c3ebf 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -988,7 +988,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
988 case SIOCADDTUNNEL: 988 case SIOCADDTUNNEL:
989 case SIOCCHGTUNNEL: 989 case SIOCCHGTUNNEL:
990 err = -EPERM; 990 err = -EPERM;
991 if (!capable(CAP_NET_ADMIN)) 991 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
992 goto done; 992 goto done;
993 993
994 err = -EFAULT; 994 err = -EFAULT;
@@ -1032,7 +1032,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1032 1032
1033 case SIOCDELTUNNEL: 1033 case SIOCDELTUNNEL:
1034 err = -EPERM; 1034 err = -EPERM;
1035 if (!capable(CAP_NET_ADMIN)) 1035 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1036 goto done; 1036 goto done;
1037 1037
1038 if (dev == sitn->fb_tunnel_dev) { 1038 if (dev == sitn->fb_tunnel_dev) {
@@ -1065,7 +1065,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1065 case SIOCDELPRL: 1065 case SIOCDELPRL:
1066 case SIOCCHGPRL: 1066 case SIOCCHGPRL:
1067 err = -EPERM; 1067 err = -EPERM;
1068 if (!capable(CAP_NET_ADMIN)) 1068 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1069 goto done; 1069 goto done;
1070 err = -EINVAL; 1070 err = -EINVAL;
1071 if (dev == sitn->fb_tunnel_dev) 1071 if (dev == sitn->fb_tunnel_dev)
@@ -1094,7 +1094,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1094 case SIOCCHG6RD: 1094 case SIOCCHG6RD:
1095 case SIOCDEL6RD: 1095 case SIOCDEL6RD:
1096 err = -EPERM; 1096 err = -EPERM;
1097 if (!capable(CAP_NET_ADMIN)) 1097 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1098 goto done; 1098 goto done;
1099 1099
1100 err = -EFAULT; 1100 err = -EFAULT;