aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Kodanev <alexey.kodanev@oracle.com>2018-02-05 07:10:35 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-05 21:21:13 -0500
commit957d761cf91cdbb175ad7d8f5472336a4d54dbf2 (patch)
treedf4f3d6438373a5ed0a6b8e0db5f48dabdb975cd
parent23ddd2612d0e9b8c61d3c70960f1b1e8b64a1c4b (diff)
sctp: fix dst refcnt leak in sctp_v6_get_dst()
When going through the bind address list in sctp_v6_get_dst() and the previously found address is better ('matchlen > bmatchlen'), the code continues to the next iteration without releasing currently held destination. Fix it by releasing 'bdst' before continue to the next iteration, and instead of introducing one more '!IS_ERR(bdst)' check for dst_release(), move the already existed one right after ip6_dst_lookup_flow(), i.e. we shouldn't proceed further if we get an error for the route lookup. Fixes: dbc2b5e9a09e ("sctp: fix src address selection if using secondary addresses for ipv6") Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/ipv6.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 5d4c15bf66d2..e35d4f73d2df 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -326,8 +326,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
326 final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); 326 final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
327 bdst = ip6_dst_lookup_flow(sk, fl6, final_p); 327 bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
328 328
329 if (!IS_ERR(bdst) && 329 if (IS_ERR(bdst))
330 ipv6_chk_addr(dev_net(bdst->dev), 330 continue;
331
332 if (ipv6_chk_addr(dev_net(bdst->dev),
331 &laddr->a.v6.sin6_addr, bdst->dev, 1)) { 333 &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
332 if (!IS_ERR_OR_NULL(dst)) 334 if (!IS_ERR_OR_NULL(dst))
333 dst_release(dst); 335 dst_release(dst);
@@ -336,8 +338,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
336 } 338 }
337 339
338 bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); 340 bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
339 if (matchlen > bmatchlen) 341 if (matchlen > bmatchlen) {
342 dst_release(bdst);
340 continue; 343 continue;
344 }
341 345
342 if (!IS_ERR_OR_NULL(dst)) 346 if (!IS_ERR_OR_NULL(dst))
343 dst_release(dst); 347 dst_release(dst);