summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/send.c
diff options
context:
space:
mode:
authorSven Eckelmann2016-03-05 16:09:16 +0100
committerAntonio Quartulli2016-05-10 12:28:29 +0200
commit273534468f050744b32054f84a1e20ee6b5bd329 (patch)
tree60e001876ccef11a01760fd9eb4539ce93979021 /net/batman-adv/send.c
parentbatman-adv: add detection for complex bridge loops (diff)
downloadkernel-qcow2-linux-273534468f050744b32054f84a1e20ee6b5bd329.tar.gz
kernel-qcow2-linux-273534468f050744b32054f84a1e20ee6b5bd329.tar.xz
kernel-qcow2-linux-273534468f050744b32054f84a1e20ee6b5bd329.zip
batman-adv: Check hard_iface refcnt before calling function
The batadv_hardif_list list is checked in many situations and the items in this list are given to specialized functions to modify the routing behavior. At the moment each of these called functions has to check itself whether the received batadv_hard_iface has a refcount > 0 before it can increase the reference counter and use it in other objects. This can easily lead to problems because it is not easily visible where all callers of a function got the batadv_hard_iface object from and whether they already hold a valid reference. Checking the reference counter directly before calling a subfunction with a pointer from the batadv_hardif_list avoids this problem. Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <a@unstable.cc>
Diffstat (limited to 'net/batman-adv/send.c')
-rw-r--r--net/batman-adv/send.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 99ea9001cf8a..f2f125684ed9 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -26,6 +26,7 @@
#include <linux/if.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
+#include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
@@ -577,10 +578,15 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (forw_packet->num_packets >= hard_iface->num_bcasts)
continue;
+ if (!kref_get_unless_zero(&hard_iface->refcount))
+ continue;
+
/* send a copy of the saved skb */
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (skb1)
batadv_send_broadcast_skb(skb1, hard_iface);
+
+ batadv_hardif_put(hard_iface);
}
rcu_read_unlock();