summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-08-14 12:34:35 +0000
committerDavid S. Miller <davem@davemloft.net>2012-08-16 14:56:11 -0700
commit476ad154f3b41dd7d9a08a2f641e28388abc2fd1 (patch)
treedf3621b3720766e4bf3a330d1114e8a1c5beace1 /net
parent48a87cc26c13b68f6cce4e9d769fcb17a6b3e4b8 (diff)
downloadlinux-3.10-476ad154f3b41dd7d9a08a2f641e28388abc2fd1.tar.gz
linux-3.10-476ad154f3b41dd7d9a08a2f641e28388abc2fd1.tar.bz2
linux-3.10-476ad154f3b41dd7d9a08a2f641e28388abc2fd1.zip
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 f65dba3afd9..c75e3f9d060 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)
u32 max_len;
struct netprio_map *map;
- rtnl_lock();
max_len = atomic_read(&max_prioidx) + 1;
map = rtnl_dereference(dev->priomap);
if (!map || map->priomap_len < max_len)
ret = extend_netdev_table(dev, max_len);
- rtnl_unlock();
return ret;
}
@@ -256,17 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,
if (!dev)
goto out_free_devname;
+ rtnl_lock();
ret = write_update_netdev_table(dev);
if (ret < 0)
goto out_put_dev;
- rcu_read_lock();
- map = rcu_dereference(dev->priomap);
+ map = rtnl_dereference(dev->priomap);
if (map)
map->priomap[prioidx] = priority;
- rcu_read_unlock();
out_put_dev:
+ rtnl_unlock();
dev_put(dev);
out_free_devname: