Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ce64c79 authored by Alexander Y. Fomichev's avatar Alexander Y. Fomichev Committed by David S. Miller
Browse files

net: fix creation adjacent device symlinks



__netdev_adjacent_dev_insert may add adjust device of different net
namespace, without proper check it leads to emergence of broken
sysfs links from/to devices in another namespace.
Fix: rewrite netdev_adjacent_is_neigh_list macro as a function,
     move net_eq check into netdev_adjacent_is_neigh_list.
     (thanks David)
     related to: 4c75431a

Signed-off-by: default avatarAlexander Fomichev <git.user@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 95e8b103
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -4809,9 +4809,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev,
	sysfs_remove_link(&(dev->dev.kobj), linkname);
}

#define netdev_adjacent_is_neigh_list(dev, dev_list) \
		(dev_list == &dev->adj_list.upper || \
		 dev_list == &dev->adj_list.lower)
static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev,
						 struct net_device *adj_dev,
						 struct list_head *dev_list)
{
	return (dev_list == &dev->adj_list.upper ||
		dev_list == &dev->adj_list.lower) &&
		net_eq(dev_net(dev), dev_net(adj_dev));
}

static int __netdev_adjacent_dev_insert(struct net_device *dev,
					struct net_device *adj_dev,
@@ -4841,7 +4846,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
	pr_debug("dev_hold for %s, because of link added from %s to %s\n",
		 adj_dev->name, dev->name, adj_dev->name);

	if (netdev_adjacent_is_neigh_list(dev, dev_list)) {
	if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) {
		ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list);
		if (ret)
			goto free_adj;
@@ -4862,7 +4867,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
	return 0;

remove_symlinks:
	if (netdev_adjacent_is_neigh_list(dev, dev_list))
	if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list))
		netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
free_adj:
	kfree(adj);
@@ -4895,8 +4900,7 @@ 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) &&
	    net_eq(dev_net(dev),dev_net(adj_dev)))
	if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list))
		netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);

	list_del_rcu(&adj->list);