| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: Antonio Quartulli <antonio@open-mesh.com> |
| Date: Wed, 23 Apr 2014 14:05:16 +0200 |
| Subject: batman-adv: fix reference counting imbalance while |
| sending fragment |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Antonio Quartulli <antonio@open-mesh.com> |
| |
| [ Upstream commit be181015a189cd141398b761ba4e79d33fe69949 ] |
| |
| In the new fragmentation code the batadv_frag_send_packet() |
| function obtains a reference to the primary_if, but it does |
| not release it upon return. |
| |
| This reference imbalance prevents the primary_if (and then |
| the related netdevice) to be properly released on shut down. |
| |
| Fix this by releasing the primary_if in batadv_frag_send_packet(). |
| |
| Introduced by ee75ed88879af88558818a5c6609d85f60ff0df4 |
| ("batman-adv: Fragment and send skbs larger than mtu") |
| |
| Cc: Martin Hundebøll <martin@hundeboll.net> |
| Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> |
| Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> |
| Acked-by: Martin Hundebøll <martin@hundeboll.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/batman-adv/fragmentation.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| --- a/net/batman-adv/fragmentation.c |
| +++ b/net/batman-adv/fragmentation.c |
| @@ -418,12 +418,13 @@ bool batadv_frag_send_packet(struct sk_b |
| struct batadv_neigh_node *neigh_node) |
| { |
| struct batadv_priv *bat_priv; |
| - struct batadv_hard_iface *primary_if; |
| + struct batadv_hard_iface *primary_if = NULL; |
| struct batadv_frag_packet frag_header; |
| struct sk_buff *skb_fragment; |
| unsigned mtu = neigh_node->if_incoming->net_dev->mtu; |
| unsigned header_size = sizeof(frag_header); |
| unsigned max_fragment_size, max_packet_size; |
| + bool ret = false; |
| |
| /* To avoid merge and refragmentation at next-hops we never send |
| * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE |
| @@ -483,7 +484,11 @@ bool batadv_frag_send_packet(struct sk_b |
| skb->len + ETH_HLEN); |
| batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
| |
| - return true; |
| + ret = true; |
| + |
| out_err: |
| - return false; |
| + if (primary_if) |
| + batadv_hardif_free_ref(primary_if); |
| + |
| + return ret; |
| } |