batman-adv: Fix general protection fault in batadv_tt_global_del_orig()

Message ID 1363487457-5413-1-git-send-email-linus.luessing@web.de (mailing list archive)
State Superseded, archived
Headers

Commit Message

Linus Lüssing March 17, 2013, 2:30 a.m. UTC
  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(+)
  

Comments

Linus Lüssing March 17, 2013, 2:42 a.m. UTC | #1
It'd probably be nicer to refactor the way we are freeing the TT
things instead of this extra rcu_barrier() which isn't that self
explanatory, even with a comment.

However this simple extra rcu_barrier() call should be an easy way
to fix this issue for now, it's probably better to refactor
afterwards.

Cheers, Linus
  
Linus Lüssing March 17, 2013, 3:22 a.m. UTC | #2
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
>
>
  

Patch

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