aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-11-15 22:03:04 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-18 20:32:45 -0500
commit5e1fccc0bfac4946932b36e4535c03957d35113d (patch)
tree2610913384552d1f663c4c3a3e82a6620b16bbf6 /net
parent00f70de09c418bfb028d03f046e39c1d301db7b2 (diff)
net: Allow userns root control of the core of the network stack.
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 ethtool ioctls. Allow binding to network devices. Allow setting the socket mark. Allow setting the socket priority. Allow setting the network device alias via sysfs. Allow setting the mtu via sysfs. Allow changing the network device flags via sysfs. Allow setting the network device group via sysfs. Allow the following network device ioctls. SIOCGMIIPHY SIOCGMIIREG SIOCSIFNAME SIOCSIFFLAGS SIOCSIFMETRIC SIOCSIFMTU SIOCSIFHWADDR SIOCSIFSLAVE SIOCADDMULTI SIOCDELMULTI SIOCSIFHWBROADCAST SIOCSMIIREG SIOCBONDENSLAVE SIOCBONDRELEASE SIOCBONDSETHWADDR SIOCBONDCHANGEACTIVE SIOCBRADDIF SIOCBRDELIF SIOCSHWTSTAMP Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c17
-rw-r--r--net/core/ethtool.c2
-rw-r--r--net/core/net-sysfs.c15
-rw-r--r--net/core/sock.c7
4 files changed, 28 insertions, 13 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 974199daa911..0afae8ba413e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5279,7 +5279,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
5279 case SIOCGMIIPHY: 5279 case SIOCGMIIPHY:
5280 case SIOCGMIIREG: 5280 case SIOCGMIIREG:
5281 case SIOCSIFNAME: 5281 case SIOCSIFNAME:
5282 if (!capable(CAP_NET_ADMIN)) 5282 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
5283 return -EPERM; 5283 return -EPERM;
5284 dev_load(net, ifr.ifr_name); 5284 dev_load(net, ifr.ifr_name);
5285 rtnl_lock(); 5285 rtnl_lock();
@@ -5300,16 +5300,25 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
5300 * - require strict serialization. 5300 * - require strict serialization.
5301 * - do not return a value 5301 * - do not return a value
5302 */ 5302 */
5303 case SIOCSIFMAP:
5304 case SIOCSIFTXQLEN:
5305 if (!capable(CAP_NET_ADMIN))
5306 return -EPERM;
5307 /* fall through */
5308 /*
5309 * These ioctl calls:
5310 * - require local superuser power.
5311 * - require strict serialization.
5312 * - do not return a value
5313 */
5303 case SIOCSIFFLAGS: 5314 case SIOCSIFFLAGS:
5304 case SIOCSIFMETRIC: 5315 case SIOCSIFMETRIC:
5305 case SIOCSIFMTU: 5316 case SIOCSIFMTU:
5306 case SIOCSIFMAP:
5307 case SIOCSIFHWADDR: 5317 case SIOCSIFHWADDR:
5308 case SIOCSIFSLAVE: 5318 case SIOCSIFSLAVE:
5309 case SIOCADDMULTI: 5319 case SIOCADDMULTI:
5310 case SIOCDELMULTI: 5320 case SIOCDELMULTI:
5311 case SIOCSIFHWBROADCAST: 5321 case SIOCSIFHWBROADCAST:
5312 case SIOCSIFTXQLEN:
5313 case SIOCSMIIREG: 5322 case SIOCSMIIREG:
5314 case SIOCBONDENSLAVE: 5323 case SIOCBONDENSLAVE:
5315 case SIOCBONDRELEASE: 5324 case SIOCBONDRELEASE:
@@ -5318,7 +5327,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
5318 case SIOCBRADDIF: 5327 case SIOCBRADDIF:
5319 case SIOCBRDELIF: 5328 case SIOCBRDELIF:
5320 case SIOCSHWTSTAMP: 5329 case SIOCSHWTSTAMP:
5321 if (!capable(CAP_NET_ADMIN)) 5330 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
5322 return -EPERM; 5331 return -EPERM;
5323 /* fall through */ 5332 /* fall through */
5324 case SIOCBONDSLAVEINFOQUERY: 5333 case SIOCBONDSLAVEINFOQUERY:
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4d64cc2e3fa9..a8705432e4b1 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1460,7 +1460,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1460 case ETHTOOL_GEEE: 1460 case ETHTOOL_GEEE:
1461 break; 1461 break;
1462 default: 1462 default:
1463 if (!capable(CAP_NET_ADMIN)) 1463 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1464 return -EPERM; 1464 return -EPERM;
1465 } 1465 }
1466 1466
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index bcf02f608cbf..c66b8c2f3b22 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -73,11 +73,12 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
73 const char *buf, size_t len, 73 const char *buf, size_t len,
74 int (*set)(struct net_device *, unsigned long)) 74 int (*set)(struct net_device *, unsigned long))
75{ 75{
76 struct net_device *net = to_net_dev(dev); 76 struct net_device *netdev = to_net_dev(dev);
77 struct net *net = dev_net(netdev);
77 unsigned long new; 78 unsigned long new;
78 int ret = -EINVAL; 79 int ret = -EINVAL;
79 80
80 if (!capable(CAP_NET_ADMIN)) 81 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
81 return -EPERM; 82 return -EPERM;
82 83
83 ret = kstrtoul(buf, 0, &new); 84 ret = kstrtoul(buf, 0, &new);
@@ -87,8 +88,8 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
87 if (!rtnl_trylock()) 88 if (!rtnl_trylock())
88 return restart_syscall(); 89 return restart_syscall();
89 90
90 if (dev_isalive(net)) { 91 if (dev_isalive(netdev)) {
91 if ((ret = (*set)(net, new)) == 0) 92 if ((ret = (*set)(netdev, new)) == 0)
92 ret = len; 93 ret = len;
93 } 94 }
94 rtnl_unlock(); 95 rtnl_unlock();
@@ -264,6 +265,9 @@ static ssize_t store_tx_queue_len(struct device *dev,
264 struct device_attribute *attr, 265 struct device_attribute *attr,
265 const char *buf, size_t len) 266 const char *buf, size_t len)
266{ 267{
268 if (!capable(CAP_NET_ADMIN))
269 return -EPERM;
270
267 return netdev_store(dev, attr, buf, len, change_tx_queue_len); 271 return netdev_store(dev, attr, buf, len, change_tx_queue_len);
268} 272}
269 273
@@ -271,10 +275,11 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
271 const char *buf, size_t len) 275 const char *buf, size_t len)
272{ 276{
273 struct net_device *netdev = to_net_dev(dev); 277 struct net_device *netdev = to_net_dev(dev);
278 struct net *net = dev_net(netdev);
274 size_t count = len; 279 size_t count = len;
275 ssize_t ret; 280 ssize_t ret;
276 281
277 if (!capable(CAP_NET_ADMIN)) 282 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
278 return -EPERM; 283 return -EPERM;
279 284
280 /* ignore trailing newline */ 285 /* ignore trailing newline */
diff --git a/net/core/sock.c b/net/core/sock.c
index 06286006a2cc..d4f7b58b3866 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -515,7 +515,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
515 515
516 /* Sorry... */ 516 /* Sorry... */
517 ret = -EPERM; 517 ret = -EPERM;
518 if (!capable(CAP_NET_RAW)) 518 if (!ns_capable(net->user_ns, CAP_NET_RAW))
519 goto out; 519 goto out;
520 520
521 ret = -EINVAL; 521 ret = -EINVAL;
@@ -696,7 +696,8 @@ set_rcvbuf:
696 break; 696 break;
697 697
698 case SO_PRIORITY: 698 case SO_PRIORITY:
699 if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN)) 699 if ((val >= 0 && val <= 6) ||
700 ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
700 sk->sk_priority = val; 701 sk->sk_priority = val;
701 else 702 else
702 ret = -EPERM; 703 ret = -EPERM;
@@ -813,7 +814,7 @@ set_rcvbuf:
813 clear_bit(SOCK_PASSSEC, &sock->flags); 814 clear_bit(SOCK_PASSSEC, &sock->flags);
814 break; 815 break;
815 case SO_MARK: 816 case SO_MARK:
816 if (!capable(CAP_NET_ADMIN)) 817 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
817 ret = -EPERM; 818 ret = -EPERM;
818 else 819 else
819 sk->sk_mark = val; 820 sk->sk_mark = val;