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);