Skip to content

Commit

Permalink
net: prevent of emerging cross-namespace symlinks
Browse files Browse the repository at this point in the history
Code manipulating sysfs symlinks on adjacent net_devices(s)
currently doesn't take into account that devices potentially
belong to different namespaces.

This patch trying to fix an issue as follows:
- check for net_ns before creating / deleting symlink.
  for now only netdev_adjacent_rename_links and
  __netdev_adjacent_dev_remove are affected, afaics
  __netdev_adjacent_dev_insert implies both net_devs
  belong to the same namespace.
- Drop all existing symlinks to / from all adj_devs before
  switching namespace and recreate them just after.

Signed-off-by: Alexander Y. Fomichev <git.user@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
gluk authored and davem330 committed Aug 25, 2014
1 parent a45e92a commit 4c75431
Showing 1 changed file with 60 additions and 1 deletion.
61 changes: 60 additions & 1 deletion net/core/dev.c
Expand Up @@ -4889,7 +4889,8 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
if (adj->master)
sysfs_remove_link(&(dev->dev.kobj), "master");

if (netdev_adjacent_is_neigh_list(dev, dev_list))
if (netdev_adjacent_is_neigh_list(dev, dev_list) &&
net_eq(dev_net(dev),dev_net(adj_dev)))
netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);

list_del_rcu(&adj->list);
Expand Down Expand Up @@ -5159,18 +5160,74 @@ void netdev_upper_dev_unlink(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);

void netdev_adjacent_add_links(struct net_device *dev)
{
struct netdev_adjacent *iter;

struct net *net = dev_net(dev);

list_for_each_entry(iter, &dev->adj_list.upper, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_add(iter->dev, dev,
&iter->dev->adj_list.lower);
netdev_adjacent_sysfs_add(dev, iter->dev,
&dev->adj_list.upper);
}

list_for_each_entry(iter, &dev->adj_list.lower, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_add(iter->dev, dev,
&iter->dev->adj_list.upper);
netdev_adjacent_sysfs_add(dev, iter->dev,
&dev->adj_list.lower);
}
}

void netdev_adjacent_del_links(struct net_device *dev)
{
struct netdev_adjacent *iter;

struct net *net = dev_net(dev);

list_for_each_entry(iter, &dev->adj_list.upper, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_del(iter->dev, dev->name,
&iter->dev->adj_list.lower);
netdev_adjacent_sysfs_del(dev, iter->dev->name,
&dev->adj_list.upper);
}

list_for_each_entry(iter, &dev->adj_list.lower, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_del(iter->dev, dev->name,
&iter->dev->adj_list.upper);
netdev_adjacent_sysfs_del(dev, iter->dev->name,
&dev->adj_list.lower);
}
}

void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
{
struct netdev_adjacent *iter;

struct net *net = dev_net(dev);

list_for_each_entry(iter, &dev->adj_list.upper, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_del(iter->dev, oldname,
&iter->dev->adj_list.lower);
netdev_adjacent_sysfs_add(iter->dev, dev,
&iter->dev->adj_list.lower);
}

list_for_each_entry(iter, &dev->adj_list.lower, list) {
if (!net_eq(net,dev_net(iter->dev)))
continue;
netdev_adjacent_sysfs_del(iter->dev, oldname,
&iter->dev->adj_list.upper);
netdev_adjacent_sysfs_add(iter->dev, dev,
Expand Down Expand Up @@ -6773,6 +6830,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char

/* Send a netdev-removed uevent to the old namespace */
kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE);
netdev_adjacent_del_links(dev);

/* Actually switch the network namespace */
dev_net_set(dev, net);
Expand All @@ -6787,6 +6845,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char

/* Send a netdev-add uevent to the new namespace */
kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
netdev_adjacent_add_links(dev);

/* Fixup kobjects */
err = device_rename(&dev->dev, dev->name);
Expand Down

0 comments on commit 4c75431

Please sign in to comment.