aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-11-15 22:03:05 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-18 20:32:45 -0500
commit52e804c6dfaa5df1e4b0e290357b82ad4e4cda2c (patch)
tree4c00a9fe6b1844701c739ae835f3aef99487ecdb
parent5e1fccc0bfac4946932b36e4535c03957d35113d (diff)
net: Allow userns root to control ipv4
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 creating raw sockets. Allow the SIOCSARP ioctl to control the arp cache. Allow the SIOCSIFFLAG ioctl to allow setting network device flags. Allow the SIOCSIFADDR ioctl to allow setting a netdevice ipv4 address. Allow the SIOCSIFBRDADDR ioctl to allow setting a netdevice ipv4 broadcast address. Allow the SIOCSIFDSTADDR ioctl to allow setting a netdevice ipv4 destination address. Allow the SIOCSIFNETMASK ioctl to allow setting a netdevice ipv4 netmask. Allow the SIOCADDRT and SIOCDELRT ioctls to allow adding and deleting ipv4 routes. Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting gre tunnels. Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting ipip tunnels. Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting ipsec virtual tunnel interfaces. Allow setting the MRT_INIT, MRT_DONE, MRT_ADD_VIF, MRT_DEL_VIF, MRT_ADD_MFC, MRT_DEL_MFC, MRT_ASSERT, MRT_PIM, MRT_TABLE socket options on multicast routing sockets. Allow setting and receiving IPOPT_CIPSO, IP_OPT_SEC, IP_OPT_SID and arbitrary ip options. Allow setting IP_SEC_POLICY/IP_XFRM_POLICY ipv4 socket option. Allow setting the IP_TRANSPARENT ipv4 socket option. Allow setting the TCP_REPAIR socket option. Allow setting the TCP_CONGESTION socket option. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/af_inet.c3
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/ip_gre.c4
-rw-r--r--net/ipv4/ip_options.c6
-rw-r--r--net/ipv4/ip_sockglue.c5
-rw-r--r--net/ipv4/ip_vti.c4
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/netfilter/arp_tables.c8
-rw-r--r--net/ipv4/netfilter/ip_tables.c8
-rw-r--r--net/ipv4/tcp.c2
-rw-r--r--net/ipv4/tcp_cong.c3
14 files changed, 30 insertions, 27 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d5e5a054123c..4f5f22061e1c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -346,7 +346,8 @@ lookup_protocol:
346 } 346 }
347 347
348 err = -EPERM; 348 err = -EPERM;
349 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) 349 if (sock->type == SOCK_RAW && !kern &&
350 !ns_capable(net->user_ns, CAP_NET_RAW))
350 goto out_rcu_unlock; 351 goto out_rcu_unlock;
351 352
352 err = -EAFNOSUPPORT; 353 err = -EAFNOSUPPORT;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 47800459e4cb..ce6fbdfd40b8 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1161,7 +1161,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1161 switch (cmd) { 1161 switch (cmd) {
1162 case SIOCDARP: 1162 case SIOCDARP:
1163 case SIOCSARP: 1163 case SIOCSARP:
1164 if (!capable(CAP_NET_ADMIN)) 1164 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1165 return -EPERM; 1165 return -EPERM;
1166 case SIOCGARP: 1166 case SIOCGARP:
1167 err = copy_from_user(&r, arg, sizeof(struct arpreq)); 1167 err = copy_from_user(&r, arg, sizeof(struct arpreq));
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 417093538916..259622a5e690 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -730,7 +730,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
730 730
731 case SIOCSIFFLAGS: 731 case SIOCSIFFLAGS:
732 ret = -EPERM; 732 ret = -EPERM;
733 if (!capable(CAP_NET_ADMIN)) 733 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
734 goto out; 734 goto out;
735 break; 735 break;
736 case SIOCSIFADDR: /* Set interface address (and family) */ 736 case SIOCSIFADDR: /* Set interface address (and family) */
@@ -738,7 +738,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
738 case SIOCSIFDSTADDR: /* Set the destination address */ 738 case SIOCSIFDSTADDR: /* Set the destination address */
739 case SIOCSIFNETMASK: /* Set the netmask for the interface */ 739 case SIOCSIFNETMASK: /* Set the netmask for the interface */
740 ret = -EPERM; 740 ret = -EPERM;
741 if (!capable(CAP_NET_ADMIN)) 741 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
742 goto out; 742 goto out;
743 ret = -EINVAL; 743 ret = -EINVAL;
744 if (sin->sin_family != AF_INET) 744 if (sin->sin_family != AF_INET)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index bce4541c6784..784716a677ce 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -488,7 +488,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
488 switch (cmd) { 488 switch (cmd) {
489 case SIOCADDRT: /* Add a route */ 489 case SIOCADDRT: /* Add a route */
490 case SIOCDELRT: /* Delete a route */ 490 case SIOCDELRT: /* Delete a route */
491 if (!capable(CAP_NET_ADMIN)) 491 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
492 return -EPERM; 492 return -EPERM;
493 493
494 if (copy_from_user(&rt, arg, sizeof(rt))) 494 if (copy_from_user(&rt, arg, sizeof(rt)))
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 127f2a1e67f5..a85ae2f7a21c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1064,7 +1064,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1064 case SIOCADDTUNNEL: 1064 case SIOCADDTUNNEL:
1065 case SIOCCHGTUNNEL: 1065 case SIOCCHGTUNNEL:
1066 err = -EPERM; 1066 err = -EPERM;
1067 if (!capable(CAP_NET_ADMIN)) 1067 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1068 goto done; 1068 goto done;
1069 1069
1070 err = -EFAULT; 1070 err = -EFAULT;
@@ -1139,7 +1139,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1139 1139
1140 case SIOCDELTUNNEL: 1140 case SIOCDELTUNNEL:
1141 err = -EPERM; 1141 err = -EPERM;
1142 if (!capable(CAP_NET_ADMIN)) 1142 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1143 goto done; 1143 goto done;
1144 1144
1145 if (dev == ign->fb_tunnel_dev) { 1145 if (dev == ign->fb_tunnel_dev) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 1dc01f9793d5..f6289bf6f332 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -409,7 +409,7 @@ int ip_options_compile(struct net *net,
409 optptr[2] += 8; 409 optptr[2] += 8;
410 break; 410 break;
411 default: 411 default:
412 if (!skb && !capable(CAP_NET_RAW)) { 412 if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
413 pp_ptr = optptr + 3; 413 pp_ptr = optptr + 3;
414 goto error; 414 goto error;
415 } 415 }
@@ -445,7 +445,7 @@ int ip_options_compile(struct net *net,
445 opt->router_alert = optptr - iph; 445 opt->router_alert = optptr - iph;
446 break; 446 break;
447 case IPOPT_CIPSO: 447 case IPOPT_CIPSO:
448 if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) { 448 if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
449 pp_ptr = optptr; 449 pp_ptr = optptr;
450 goto error; 450 goto error;
451 } 451 }
@@ -458,7 +458,7 @@ int ip_options_compile(struct net *net,
458 case IPOPT_SEC: 458 case IPOPT_SEC:
459 case IPOPT_SID: 459 case IPOPT_SID:
460 default: 460 default:
461 if (!skb && !capable(CAP_NET_RAW)) { 461 if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
462 pp_ptr = optptr; 462 pp_ptr = optptr;
463 goto error; 463 goto error;
464 } 464 }
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 14bbfcf717ac..3c9d20880283 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -989,13 +989,14 @@ mc_msf_out:
989 case IP_IPSEC_POLICY: 989 case IP_IPSEC_POLICY:
990 case IP_XFRM_POLICY: 990 case IP_XFRM_POLICY:
991 err = -EPERM; 991 err = -EPERM;
992 if (!capable(CAP_NET_ADMIN)) 992 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
993 break; 993 break;
994 err = xfrm_user_policy(sk, optname, optval, optlen); 994 err = xfrm_user_policy(sk, optname, optval, optlen);
995 break; 995 break;
996 996
997 case IP_TRANSPARENT: 997 case IP_TRANSPARENT:
998 if (!!val && !capable(CAP_NET_RAW) && !capable(CAP_NET_ADMIN)) { 998 if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
999 !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
999 err = -EPERM; 1000 err = -EPERM;
1000 break; 1001 break;
1001 } 1002 }
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index f4a825d3bd7f..c3a4233c0ac2 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -488,7 +488,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
488 case SIOCADDTUNNEL: 488 case SIOCADDTUNNEL:
489 case SIOCCHGTUNNEL: 489 case SIOCCHGTUNNEL:
490 err = -EPERM; 490 err = -EPERM;
491 if (!capable(CAP_NET_ADMIN)) 491 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
492 goto done; 492 goto done;
493 493
494 err = -EFAULT; 494 err = -EFAULT;
@@ -553,7 +553,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
553 553
554 case SIOCDELTUNNEL: 554 case SIOCDELTUNNEL:
555 err = -EPERM; 555 err = -EPERM;
556 if (!capable(CAP_NET_ADMIN)) 556 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
557 goto done; 557 goto done;
558 558
559 if (dev == ipn->fb_tunnel_dev) { 559 if (dev == ipn->fb_tunnel_dev) {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index c26c1717c1db..191fc24a745a 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -691,7 +691,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
691 case SIOCADDTUNNEL: 691 case SIOCADDTUNNEL:
692 case SIOCCHGTUNNEL: 692 case SIOCCHGTUNNEL:
693 err = -EPERM; 693 err = -EPERM;
694 if (!capable(CAP_NET_ADMIN)) 694 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
695 goto done; 695 goto done;
696 696
697 err = -EFAULT; 697 err = -EFAULT;
@@ -735,7 +735,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
735 735
736 case SIOCDELTUNNEL: 736 case SIOCDELTUNNEL:
737 err = -EPERM; 737 err = -EPERM;
738 if (!capable(CAP_NET_ADMIN)) 738 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
739 goto done; 739 goto done;
740 740
741 if (dev == ipn->fb_tunnel_dev) { 741 if (dev == ipn->fb_tunnel_dev) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 6168c4dc58b1..adf3d349566f 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1213,7 +1213,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1213 1213
1214 if (optname != MRT_INIT) { 1214 if (optname != MRT_INIT) {
1215 if (sk != rcu_access_pointer(mrt->mroute_sk) && 1215 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
1216 !capable(CAP_NET_ADMIN)) 1216 !ns_capable(net->user_ns, CAP_NET_ADMIN))
1217 return -EACCES; 1217 return -EACCES;
1218 } 1218 }
1219 1219
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 97e61eadf580..3ea4127404d6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1533,7 +1533,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
1533{ 1533{
1534 int ret; 1534 int ret;
1535 1535
1536 if (!capable(CAP_NET_ADMIN)) 1536 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1537 return -EPERM; 1537 return -EPERM;
1538 1538
1539 switch (cmd) { 1539 switch (cmd) {
@@ -1677,7 +1677,7 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
1677{ 1677{
1678 int ret; 1678 int ret;
1679 1679
1680 if (!capable(CAP_NET_ADMIN)) 1680 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1681 return -EPERM; 1681 return -EPERM;
1682 1682
1683 switch (cmd) { 1683 switch (cmd) {
@@ -1698,7 +1698,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
1698{ 1698{
1699 int ret; 1699 int ret;
1700 1700
1701 if (!capable(CAP_NET_ADMIN)) 1701 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1702 return -EPERM; 1702 return -EPERM;
1703 1703
1704 switch (cmd) { 1704 switch (cmd) {
@@ -1722,7 +1722,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1722{ 1722{
1723 int ret; 1723 int ret;
1724 1724
1725 if (!capable(CAP_NET_ADMIN)) 1725 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1726 return -EPERM; 1726 return -EPERM;
1727 1727
1728 switch (cmd) { 1728 switch (cmd) {
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 170b1fdd6b72..17c5e06da662 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1846,7 +1846,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1846{ 1846{
1847 int ret; 1847 int ret;
1848 1848
1849 if (!capable(CAP_NET_ADMIN)) 1849 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1850 return -EPERM; 1850 return -EPERM;
1851 1851
1852 switch (cmd) { 1852 switch (cmd) {
@@ -1961,7 +1961,7 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1961{ 1961{
1962 int ret; 1962 int ret;
1963 1963
1964 if (!capable(CAP_NET_ADMIN)) 1964 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1965 return -EPERM; 1965 return -EPERM;
1966 1966
1967 switch (cmd) { 1967 switch (cmd) {
@@ -1983,7 +1983,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1983{ 1983{
1984 int ret; 1984 int ret;
1985 1985
1986 if (!capable(CAP_NET_ADMIN)) 1986 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1987 return -EPERM; 1987 return -EPERM;
1988 1988
1989 switch (cmd) { 1989 switch (cmd) {
@@ -2008,7 +2008,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2008{ 2008{
2009 int ret; 2009 int ret;
2010 2010
2011 if (!capable(CAP_NET_ADMIN)) 2011 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
2012 return -EPERM; 2012 return -EPERM;
2013 2013
2014 switch (cmd) { 2014 switch (cmd) {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4aefa0b42c2e..e6eace1c2bdb 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2304,7 +2304,7 @@ void tcp_sock_destruct(struct sock *sk)
2304 2304
2305static inline bool tcp_can_repair_sock(const struct sock *sk) 2305static inline bool tcp_can_repair_sock(const struct sock *sk)
2306{ 2306{
2307 return capable(CAP_NET_ADMIN) && 2307 return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
2308 ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED)); 2308 ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
2309} 2309}
2310 2310
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1432cdb0644c..baf28611b334 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -259,7 +259,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
259 if (!ca) 259 if (!ca)
260 err = -ENOENT; 260 err = -ENOENT;
261 261
262 else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || capable(CAP_NET_ADMIN))) 262 else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
263 ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)))
263 err = -EPERM; 264 err = -EPERM;
264 265
265 else if (!try_module_get(ca->owner)) 266 else if (!try_module_get(ca->owner))