[Devel] [PATCH 1/2] net: allow containers create bridges with CAP_VE_NET_ADMIN

Kirill Tkhai ktkhai at odin.com
Thu Jun 18 03:28:39 PDT 2015


Port patch diff-ve-net-ioctl-allow-change-net-device-name-with-CAP_VE_NET_ADMIN
from 2.6.32:

It is for docker task.

CAP_NET_ADMIN is raised in vzctl(function CapBuildMask) for ve with
VE_FEATURE_BRIDGE set(vzctl set $veid --features bridge:on --save).
Because it is demanded by kernel to have CAP_NET_ADMIN for operations
like add/delete bridge, set: forward delay, hello time, max age, ageing
time, Spanning Tree Protocol state, via_phys_dev, priority or
add/remove port.

This patch makes that we no longer need to give this cap from vzctl for
bridges feature. It allows to do all mentioned above operations with
CAP_VE_NET_ADMIN.

Test:
In VE with VE_FEATURE_BRIDGE and without CAP_NET_ADMIN(tested  with
12-th bit removed in caps bounding set on create of ve)
bridge create/delete normaly:

cat /proc/self/status | grep CapBnd
CapBnd:	00000000fdecefff

brctl addbr mybridge1
brctl delbr mybridge1

bridged docker-container works fine too(wordpress + mysql)

v2: tested, found 3 more places where need to allow ve-admin, add
description.
v3: disable SIOCADDMULTI, SIOCDELMULTI, SIOCSIFHWBROADCAST,
SIOCSMIIREG, SIOCBONDENSLAVE, SIOCBONDRELEASE, SIOCBONDSETHWADDR,
SIOCBONDCHANGEACTIVE, SIOCSHWTSTAMP inside a CT.

https://jira.sw.ru/browse/PSBM-29808

Signed-off-by: Pavel Tikhomirov <ptikhomirov at parallels.com>
Signed-off-by: Kirill Tkhai <ktkhai at odin.com>
---
 net/bridge/br_ioctl.c |   33 ++++++++++++++++++++++-----------
 net/core/dev_ioctl.c  |    8 ++++----
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 98447b8..45c4c22 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -89,7 +89,8 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
 	struct net_device *dev;
 	int ret;
 
-	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+	if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
+	    !ns_capable(net->user_ns, CAP_VE_NET_ADMIN))
 		return -EPERM;
 
 	dev = __dev_get_by_index(net, ifindex);
@@ -179,25 +180,29 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	}
 
 	case BRCTL_SET_BRIDGE_FORWARD_DELAY:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		return br_set_forward_delay(br, args[1]);
 
 	case BRCTL_SET_BRIDGE_HELLO_TIME:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		return br_set_hello_time(br, args[1]);
 
 	case BRCTL_SET_BRIDGE_MAX_AGE:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		return br_set_max_age(br, args[1]);
 
 	case BRCTL_SET_AGEING_TIME:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		br->ageing_time = clock_t_to_jiffies(args[1]);
@@ -237,14 +242,16 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	}
 
 	case BRCTL_SET_BRIDGE_STP_STATE:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		br_stp_set_enabled(br, args[1]);
 		return 0;
 
 	case BRCTL_SET_BRIDGE_PRIORITY:
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		spin_lock_bh(&br->lock);
@@ -257,7 +264,8 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		struct net_bridge_port *p;
 		int ret;
 
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		spin_lock_bh(&br->lock);
@@ -274,7 +282,8 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		struct net_bridge_port *p;
 		int ret;
 
-		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(dev_net(dev)->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		spin_lock_bh(&br->lock);
@@ -331,7 +340,8 @@ static int old_deviceless(struct net *net, void __user *uarg)
 	{
 		char buf[IFNAMSIZ];
 
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(net->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
@@ -364,7 +374,8 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar
 	{
 		char buf[IFNAMSIZ];
 
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
+		    !ns_capable(net->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
 
 		if (copy_from_user(buf, uarg, IFNAMSIZ))
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index d407219..2be924c 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -499,9 +499,13 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	 *	- do not return a value
 	 */
 	case SIOCSIFMAP:
+	case SIOCSIFSLAVE:
 	case SIOCSIFMTU:
 	case SIOCSIFHWADDR:
 	case SIOCSIFFLAGS:
+	case SIOCSIFMETRIC:
+	case SIOCBRADDIF:
+	case SIOCBRDELIF:
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
 				!ns_capable(net->user_ns, CAP_VE_NET_ADMIN))
 			return -EPERM;
@@ -511,8 +515,6 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		rtnl_unlock();
 		return ret;
 
-	case SIOCSIFMETRIC:
-	case SIOCSIFSLAVE:
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
 	case SIOCSIFHWBROADCAST:
@@ -521,8 +523,6 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	case SIOCBONDRELEASE:
 	case SIOCBONDSETHWADDR:
 	case SIOCBONDCHANGEACTIVE:
-	case SIOCBRADDIF:
-	case SIOCBRDELIF:
 	case SIOCSHWTSTAMP:
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;




More information about the Devel mailing list