aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2011-05-03 19:57:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-11 14:50:30 -0400
commit9ca99eeca0cfe839c481f3350988e9ed94188567 (patch)
tree941425d359c2b43a2a2009155f69f0008306ab2c /net
parent8f9cb77d6d213c153b0571f494df0c24456aaf47 (diff)
mac80211: Check size of a new mesh path table for changes since allocation.
Not sure if I'm chasing a ghost here, seems like the mesh_path->size_order needs to be inside an RCU-read section to prevent that value from changing between table allocation and copying. We have observed crashes that might be caused by this. Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/mesh_pathtbl.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 7776ae5a8f15..c1a2bf2aa2de 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -76,7 +76,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl,
76 < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) 76 < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
77 return -EAGAIN; 77 return -EAGAIN;
78 78
79
80 newtbl->free_node = oldtbl->free_node; 79 newtbl->free_node = oldtbl->free_node;
81 newtbl->mean_chain_len = oldtbl->mean_chain_len; 80 newtbl->mean_chain_len = oldtbl->mean_chain_len;
82 newtbl->copy_node = oldtbl->copy_node; 81 newtbl->copy_node = oldtbl->copy_node;
@@ -329,7 +328,8 @@ void mesh_mpath_table_grow(void)
329{ 328{
330 struct mesh_table *oldtbl, *newtbl; 329 struct mesh_table *oldtbl, *newtbl;
331 330
332 newtbl = mesh_table_alloc(mesh_paths->size_order + 1); 331 rcu_read_lock();
332 newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1);
333 if (!newtbl) 333 if (!newtbl)
334 return; 334 return;
335 write_lock(&pathtbl_resize_lock); 335 write_lock(&pathtbl_resize_lock);
@@ -339,6 +339,7 @@ void mesh_mpath_table_grow(void)
339 write_unlock(&pathtbl_resize_lock); 339 write_unlock(&pathtbl_resize_lock);
340 return; 340 return;
341 } 341 }
342 rcu_read_unlock();
342 rcu_assign_pointer(mesh_paths, newtbl); 343 rcu_assign_pointer(mesh_paths, newtbl);
343 write_unlock(&pathtbl_resize_lock); 344 write_unlock(&pathtbl_resize_lock);
344 345
@@ -350,7 +351,8 @@ void mesh_mpp_table_grow(void)
350{ 351{
351 struct mesh_table *oldtbl, *newtbl; 352 struct mesh_table *oldtbl, *newtbl;
352 353
353 newtbl = mesh_table_alloc(mpp_paths->size_order + 1); 354 rcu_read_lock();
355 newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1);
354 if (!newtbl) 356 if (!newtbl)
355 return; 357 return;
356 write_lock(&pathtbl_resize_lock); 358 write_lock(&pathtbl_resize_lock);
@@ -360,6 +362,7 @@ void mesh_mpp_table_grow(void)
360 write_unlock(&pathtbl_resize_lock); 362 write_unlock(&pathtbl_resize_lock);
361 return; 363 return;
362 } 364 }
365 rcu_read_unlock();
363 rcu_assign_pointer(mpp_paths, newtbl); 366 rcu_assign_pointer(mpp_paths, newtbl);
364 write_unlock(&pathtbl_resize_lock); 367 write_unlock(&pathtbl_resize_lock);
365 368