1 |
commit 7ce64c79c4decdeb1afe0bf2f6ef834b382871d1 |
2 |
Author: Alexander Y. Fomichev <git.user@gmail.com> |
3 |
Date: Mon Sep 15 14:22:10 2014 +0400 |
4 |
|
5 |
net: fix creation adjacent device symlinks |
6 |
|
7 |
__netdev_adjacent_dev_insert may add adjust device of different net |
8 |
namespace, without proper check it leads to emergence of broken |
9 |
sysfs links from/to devices in another namespace. |
10 |
Fix: rewrite netdev_adjacent_is_neigh_list macro as a function, |
11 |
move net_eq check into netdev_adjacent_is_neigh_list. |
12 |
(thanks David) |
13 |
related to: 4c75431ac3520631f1d9e74aa88407e6374dbbc4 |
14 |
|
15 |
Signed-off-by: Alexander Fomichev <git.user@gmail.com> |
16 |
Signed-off-by: David S. Miller <davem@davemloft.net> |
17 |
--- |
18 |
net/core/dev.c | 18 +++++++++++------- |
19 |
1 file changed, 11 insertions(+), 7 deletions(-) |
20 |
|
21 |
diff --git a/net/core/dev.c b/net/core/dev.c |
22 |
index ab9a165..cf8a95f 100644 |
23 |
--- a/net/core/dev.c |
24 |
+++ b/net/core/dev.c |
25 |
@@ -4809,9 +4809,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, |
26 |
sysfs_remove_link(&(dev->dev.kobj), linkname); |
27 |
} |
28 |
|
29 |
-#define netdev_adjacent_is_neigh_list(dev, dev_list) \ |
30 |
- (dev_list == &dev->adj_list.upper || \ |
31 |
- dev_list == &dev->adj_list.lower) |
32 |
+static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, |
33 |
+ struct net_device *adj_dev, |
34 |
+ struct list_head *dev_list) |
35 |
+{ |
36 |
+ return (dev_list == &dev->adj_list.upper || |
37 |
+ dev_list == &dev->adj_list.lower) && |
38 |
+ net_eq(dev_net(dev), dev_net(adj_dev)); |
39 |
+} |
40 |
|
41 |
static int __netdev_adjacent_dev_insert(struct net_device *dev, |
42 |
struct net_device *adj_dev, |
43 |
@@ -4841,7 +4846,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, |
44 |
pr_debug("dev_hold for %s, because of link added from %s to %s\n", |
45 |
adj_dev->name, dev->name, adj_dev->name); |
46 |
|
47 |
- if (netdev_adjacent_is_neigh_list(dev, dev_list)) { |
48 |
+ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { |
49 |
ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); |
50 |
if (ret) |
51 |
goto free_adj; |
52 |
@@ -4862,7 +4867,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, |
53 |
return 0; |
54 |
|
55 |
remove_symlinks: |
56 |
- if (netdev_adjacent_is_neigh_list(dev, dev_list)) |
57 |
+ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
58 |
netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
59 |
free_adj: |
60 |
kfree(adj); |
61 |
@@ -4895,8 +4900,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, |
62 |
if (adj->master) |
63 |
sysfs_remove_link(&(dev->dev.kobj), "master"); |
64 |
|
65 |
- if (netdev_adjacent_is_neigh_list(dev, dev_list) && |
66 |
- net_eq(dev_net(dev),dev_net(adj_dev))) |
67 |
+ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
68 |
netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
69 |
|
70 |
list_del_rcu(&adj->list); |