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

Pavel Tikhomirov ptikhomirov at odin.com
Thu Jun 18 05:43:14 PDT 2015


Acked-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>

On 06/18/2015 01:28 PM, Kirill Tkhai wrote:
> 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;
>

-- 
Best regards, Tikhomirov Pavel
Software Developer, Odin.



More information about the Devel mailing list