| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: Antonio Quartulli <antonio@open-mesh.com> |
| Date: Fri, 2 May 2014 01:35:13 +0200 |
| Subject: batman-adv: increase orig refcount when storing ref in |
| gw_node |
| |
| From: Antonio Quartulli <antonio@open-mesh.com> |
| |
| [ Upstream commit 377fe0f968b30a1a714fab53a908061914f30e26 ] |
| |
| A pointer to the orig_node representing a bat-gateway is |
| stored in the gw_node->orig_node member, but the refcount |
| for such orig_node is never increased. |
| This leads to memory faults when gw_node->orig_node is accessed |
| and the originator has already been freed. |
| |
| Fix this by increasing the refcount on gw_node creation |
| and decreasing it on gw_node free. |
| |
| Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> |
| Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/batman-adv/gateway_client.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| --- a/net/batman-adv/gateway_client.c |
| +++ b/net/batman-adv/gateway_client.c |
| @@ -42,8 +42,10 @@ |
| |
| static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) |
| { |
| - if (atomic_dec_and_test(&gw_node->refcount)) |
| + if (atomic_dec_and_test(&gw_node->refcount)) { |
| + batadv_orig_node_free_ref(gw_node->orig_node); |
| kfree_rcu(gw_node, rcu); |
| + } |
| } |
| |
| static struct batadv_gw_node * |
| @@ -408,9 +410,14 @@ static void batadv_gw_node_add(struct ba |
| if (gateway->bandwidth_down == 0) |
| return; |
| |
| + if (!atomic_inc_not_zero(&orig_node->refcount)) |
| + return; |
| + |
| gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); |
| - if (!gw_node) |
| + if (!gw_node) { |
| + batadv_orig_node_free_ref(orig_node); |
| return; |
| + } |
| |
| INIT_HLIST_NODE(&gw_node->list); |
| gw_node->orig_node = orig_node; |