diff options
author | Sven Eckelmann <sven@narfation.org> | 2016-03-05 16:09:16 +0100 |
---|---|---|
committer | Antonio Quartulli <a@unstable.cc> | 2016-05-10 12:28:29 +0200 |
commit | 273534468f050744b32054f84a1e20ee6b5bd329 (patch) | |
tree | 60e001876ccef11a01760fd9eb4539ce93979021 /net/batman-adv/bat_iv_ogm.c | |
parent | batman-adv: add detection for complex bridge loops (diff) | |
download | linux-273534468f050744b32054f84a1e20ee6b5bd329.tar.xz 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/bat_iv_ogm.c')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 8c1710bba803..57e9962c7090 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -987,9 +987,15 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) list_for_each_entry_rcu(tmp_hard_iface, &batadv_hardif_list, list) { if (tmp_hard_iface->soft_iface != hard_iface->soft_iface) continue; + + if (!kref_get_unless_zero(&tmp_hard_iface->refcount)) + continue; + batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len, hard_iface, tmp_hard_iface, 1, send_time); + + batadv_hardif_put(tmp_hard_iface); } rcu_read_unlock(); @@ -1767,8 +1773,13 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, if (hard_iface->soft_iface != bat_priv->soft_iface) continue; + if (!kref_get_unless_zero(&hard_iface->refcount)) + continue; + batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node, if_incoming, hard_iface); + + batadv_hardif_put(hard_iface); } rcu_read_unlock(); |