diff options
author | Javier Cardona <javier@cozybit.com> | 2011-05-03 19:57:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-11 14:50:30 -0400 |
commit | 9ca99eeca0cfe839c481f3350988e9ed94188567 (patch) | |
tree | 941425d359c2b43a2a2009155f69f0008306ab2c /net/mac80211/mesh_pathtbl.c | |
parent | 8f9cb77d6d213c153b0571f494df0c24456aaf47 (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/mac80211/mesh_pathtbl.c')
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 9 |
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 | ||