diff options
author | Sven Eckelmann <sven@narfation.org> | 2016-05-06 05:43:39 -0400 |
---|---|---|
committer | Antonio Quartulli <a@unstable.cc> | 2016-05-17 23:49:40 -0400 |
commit | 71f9d27daa2cbcca7159c27f0c0c381cc2dd1053 (patch) | |
tree | 5feaba3744a53cfb781720c9438cb9f03faaa6f3 | |
parent | a45e932a3c58eac11a7458c6888910e23f615077 (diff) |
batman-adv: Fix refcnt leak in batadv_v_neigh_*
The functions batadv_neigh_ifinfo_get increase the reference counter of the
batadv_neigh_ifinfo. These have to be reduced again when the reference is
not used anymore to correctly free the objects.
Fixes: 9786906022eb ("batman-adv: B.A.T.M.A.N. V - implement neighbor comparison API calls")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <a@unstable.cc>
-rw-r--r-- | net/batman-adv/bat_v.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 50bfcf87f569..4f626a6b8ebd 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c | |||
@@ -256,14 +256,23 @@ static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, | |||
256 | struct batadv_hard_iface *if_outgoing2) | 256 | struct batadv_hard_iface *if_outgoing2) |
257 | { | 257 | { |
258 | struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; | 258 | struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; |
259 | int ret = 0; | ||
259 | 260 | ||
260 | ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); | 261 | ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); |
262 | if (WARN_ON(!ifinfo1)) | ||
263 | goto err_ifinfo1; | ||
264 | |||
261 | ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | 265 | ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); |
266 | if (WARN_ON(!ifinfo2)) | ||
267 | goto err_ifinfo2; | ||
262 | 268 | ||
263 | if (WARN_ON(!ifinfo1 || !ifinfo2)) | 269 | ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput; |
264 | return 0; | ||
265 | 270 | ||
266 | return ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput; | 271 | batadv_neigh_ifinfo_put(ifinfo2); |
272 | err_ifinfo2: | ||
273 | batadv_neigh_ifinfo_put(ifinfo1); | ||
274 | err_ifinfo1: | ||
275 | return ret; | ||
267 | } | 276 | } |
268 | 277 | ||
269 | static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, | 278 | static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, |
@@ -273,17 +282,26 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, | |||
273 | { | 282 | { |
274 | struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; | 283 | struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; |
275 | u32 threshold; | 284 | u32 threshold; |
285 | bool ret = false; | ||
276 | 286 | ||
277 | ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); | 287 | ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); |
278 | ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | 288 | if (WARN_ON(!ifinfo1)) |
289 | goto err_ifinfo1; | ||
279 | 290 | ||
280 | if (WARN_ON(!ifinfo1 || !ifinfo2)) | 291 | ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); |
281 | return false; | 292 | if (WARN_ON(!ifinfo2)) |
293 | goto err_ifinfo2; | ||
282 | 294 | ||
283 | threshold = ifinfo1->bat_v.throughput / 4; | 295 | threshold = ifinfo1->bat_v.throughput / 4; |
284 | threshold = ifinfo1->bat_v.throughput - threshold; | 296 | threshold = ifinfo1->bat_v.throughput - threshold; |
285 | 297 | ||
286 | return ifinfo2->bat_v.throughput > threshold; | 298 | ret = ifinfo2->bat_v.throughput > threshold; |
299 | |||
300 | batadv_neigh_ifinfo_put(ifinfo2); | ||
301 | err_ifinfo2: | ||
302 | batadv_neigh_ifinfo_put(ifinfo1); | ||
303 | err_ifinfo1: | ||
304 | return ret; | ||
287 | } | 305 | } |
288 | 306 | ||
289 | static struct batadv_algo_ops batadv_batman_v __read_mostly = { | 307 | static struct batadv_algo_ops batadv_batman_v __read_mostly = { |