From: Denis V. Lunev <[email protected]>
vti6_init_net() frees the vti6_net of every container netns. vti6
tunnels cannot be created in a container, but the host can move one in
with "ip link set v6 netns <CT>". vti6_dellink() and
vti6_siocdevprivate() look ip6n up in dev_net(dev) and read
ip6n->fb_tnl_dev, so the node panics on a NULL pointer dereference when
container root deletes the tunnel or issues a tunnel ioctl on it, when
the container stops and cleanup_net() deletes it, or when ip6_vti is
unloaded. SIOCADDTUNNEL on such a device also walks the NULL hash in
vti6_locate().
Take the netns from t->net in both, as ip6_tunnel and sit do. For a
tunnel that was not moved t->net is dev_net(dev), so the host sees no
change. For a moved one the CAP_NET_ADMIN checks of the ioctls now run
against the creation netns and container root gets EPERM, as it does
for ip6tnl and sit; "ip link del" keeps working.
This relies on the backports of mainline 11b326fb0a37 ("ip6: vti: Use
ip6_tnl.net in vti6_changelink()."), which moves vti6_changelink() and
vti6_update() to t->net, and d289d5307762 ("ip6_vti: set
netns_immutable on the fallback device."), which keeps ip6_vti0 in its
netns so the fb_tnl_dev comparisons keep their meaning.
Fixes: b03d021d2fd6 ("ve/net: ip6_vti: skip per net init in ve")
https://virtuozzo.atlassian.net/browse/VSTOR-154348
Feature: net: whitelist allowed Container network devices
Signed-off-by: Denis V. Lunev <[email protected]>
---
net/ipv6/ip6_vti.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 420830c5e064..40c6298c8b13 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -805,8 +805,9 @@ vti6_siocdevprivate(struct net_device *dev, struct ifreq
*ifr, void __user *data
int err = 0;
struct ip6_tnl_parm2 p;
struct __ip6_tnl_parm p1;
+ struct ip6_tnl *self = netdev_priv(dev);
struct ip6_tnl *t = NULL;
- struct net *net = dev_net(dev);
+ struct net *net = self->net;
struct vti6_net *ip6n = net_generic(net, vti6_net_id);
memset(&p1, 0, sizeof(p1));
@@ -842,8 +843,6 @@ vti6_siocdevprivate(struct net_device *dev, struct ifreq
*ifr, void __user *data
break;
vti6_parm_from_user(&p1, &p);
if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
- struct ip6_tnl *self = netdev_priv(dev);
-
err = -EPERM;
if (!ns_capable(self->net->user_ns, CAP_NET_ADMIN))
break;
@@ -1034,8 +1033,8 @@ static int vti6_newlink(struct net *src_net, struct
net_device *dev,
static void vti6_dellink(struct net_device *dev, struct list_head *head)
{
- struct net *net = dev_net(dev);
- struct vti6_net *ip6n = net_generic(net, vti6_net_id);
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct vti6_net *ip6n = net_generic(t->net, vti6_net_id);
if (dev != ip6n->fb_tnl_dev)
unregister_netdevice_queue(dev, head);
--
2.53.0
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel