diff options
author | John Fastabend <john.r.fastabend@intel.com> | 2012-08-14 12:34:35 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-16 14:56:11 -0700 |
commit | 476ad154f3b41dd7d9a08a2f641e28388abc2fd1 (patch) | |
tree | df3621b3720766e4bf3a330d1114e8a1c5beace1 /net/core | |
parent | 48a87cc26c13b68f6cce4e9d769fcb17a6b3e4b8 (diff) | |
download | talos-op-linux-476ad154f3b41dd7d9a08a2f641e28388abc2fd1.tar.gz talos-op-linux-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/core')
-rw-r--r-- | net/core/netprio_cgroup.c | 8 |
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) 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: |