Subject: [PATCH 3.4.y 3/3] net: netprio: fix cgrp create and write priomap race

From: Li Zefan <[email-masked]>
Date: Sat, 26 Jan 2013 12:42:22 +0800

From: John Fastabend <[email-masked]>

commit 476ad154f3b41dd7d9a08a2f641e28388abc2fd1 upstream.

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 <[email-masked]>
Reported-by: Al Viro <[email-masked]>
Signed-off-by: John Fastabend <[email-masked]>
Acked-by: Neil Horman <[email-masked]>
Signed-off-by: David S. Miller <[email-masked]>
Signed-off-by: Li Zefan <[email-masked]>
---
 net/core/netprio_cgroup.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index dca347e..eb07ea9 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -112,12 +112,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;
 }
@@ -267,17 +265,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:
-- 
1.8.0.2