Hrm, forget it, this patch isn't sufficient...
batadv_nc_free() is scheduling batadv_orig_node_free_rcu()s, too. And actually, batadv_tt_free() itself does so, too, before it frees its global TT hash... which can backfire after the global TT hash freeing...
Ok, a more invasive patch to properly fix this issue is needed.
Gesendet: Sonntag, 17. März 2013 um 03:30 Uhr Von: "Linus Lüssing" linus.luessing@web.de An: b.a.t.m.a.n@lists.open-mesh.org Cc: "Linus Lüssing" linus.luessing@web.de Betreff: [PATCH] batman-adv: Fix general protection fault in batadv_tt_global_del_orig()
On shutdown a race condition where we access a just freed global TT hash might occure:
batadv_mesh_free()->batadv_originator_free() schedules the batadv_orig_node_free_rcu().
Before batadv_orig_node_free_rcu() is executed (which happens on the rcu_barrier() call in batadv_exit() the latest), batadv_mesh_free()->batadv_tt_free()->batadv_tt_global_table_free()-> batadv_hash_destroy(hash)->kfree(hash) is called, freeing the global tt hash.
When batadv_orig_node_free_rcu()->batadv_tt_global_del_orig() now gets executed it tries to access this just freed global tt hash, causing a kernel panic.
This patch tries to fix this by waiting for any just scheduled batadv_orig_node_free_rcu() to finish via an extra rcu_barrier() call before freeing the global TT hash.
Signed-off-by: Linus Lüssing linus.luessing@web.de
Ref: #169
main.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/main.c b/main.c index 62b1f89..0afc171 100644 --- a/main.c +++ b/main.c @@ -164,6 +164,11 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_gw_node_purge(bat_priv); batadv_originator_free(bat_priv);
/* Wait for any batadv_orig_node_free_rcu() to finish,
* they access the soon to be freed global TT hash */
rcu_barrier();
batadv_nc_free(bat_priv);
batadv_tt_free(bat_priv);
-- 1.7.10.4