aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-08-14 08:34:35 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-16 17:56:11 -0400
commit476ad154f3b41dd7d9a08a2f641e28388abc2fd1 (patch)
treedf3621b3720766e4bf3a330d1114e8a1c5beace1 /net
parent48a87cc26c13b68f6cce4e9d769fcb17a6b3e4b8 (diff)
net: netprio: fix cgrp create and write priomap race
A race exists where creating cgroups and also updating the priomap may result in losing a priomap update. This is because priomap writers are not protected by rtnl_lock. Move priority writer into rtnl_lock()/rtnl_unlock(). CC: Neil Horman <nhorman@tuxdriver.com> Reported-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/netprio_cgroup.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index f65dba3afd99..c75e3f9d060f 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -101,12 +101,10 @@ static int write_update_netdev_table(struct net_device *dev)
101 u32 max_len; 101 u32 max_len;
102 struct netprio_map *map; 102 struct netprio_map *map;
103 103
104 rtnl_lock();
105 max_len = atomic_read(&max_prioidx) + 1; 104 max_len = atomic_read(&max_prioidx) + 1;
106 map = rtnl_dereference(dev->priomap); 105 map = rtnl_dereference(dev->priomap);
107 if (!map || map->priomap_len < max_len) 106 if (!map || map->priomap_len < max_len)
108 ret = extend_netdev_table(dev, max_len); 107 ret = extend_netdev_table(dev, max_len);
109 rtnl_unlock();
110 108
111 return ret; 109 return ret;
112} 110}
@@ -256,17 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,
256 if (!dev) 254 if (!dev)
257 goto out_free_devname; 255 goto out_free_devname;
258 256
257 rtnl_lock();
259 ret = write_update_netdev_table(dev); 258 ret = write_update_netdev_table(dev);
260 if (ret < 0) 259 if (ret < 0)
261 goto out_put_dev; 260 goto out_put_dev;
262 261
263 rcu_read_lock(); 262 map = rtnl_dereference(dev->priomap);
264 map = rcu_dereference(dev->priomap);
265 if (map) 263 if (map)
266 map->priomap[prioidx] = priority; 264 map->priomap[prioidx] = priority;
267 rcu_read_unlock();
268 265
269out_put_dev: 266out_put_dev:
267 rtnl_unlock();
270 dev_put(dev); 268 dev_put(dev);
271 269
272out_free_devname: 270out_free_devname: