0006-sctp-fix-dst-refcnt-leak-in-sctp_v6_get_dst.patch 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Alexey Kodanev <[email protected]>
  3. Date: Mon, 5 Feb 2018 15:10:35 +0300
  4. Subject: [PATCH] sctp: fix dst refcnt leak in sctp_v6_get_dst()
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. When going through the bind address list in sctp_v6_get_dst() and
  9. the previously found address is better ('matchlen > bmatchlen'),
  10. the code continues to the next iteration without releasing currently
  11. held destination.
  12. Fix it by releasing 'bdst' before continue to the next iteration, and
  13. instead of introducing one more '!IS_ERR(bdst)' check for dst_release(),
  14. move the already existed one right after ip6_dst_lookup_flow(), i.e. we
  15. shouldn't proceed further if we get an error for the route lookup.
  16. Fixes: dbc2b5e9a09e ("sctp: fix src address selection if using secondary addresses for ipv6")
  17. Signed-off-by: Alexey Kodanev <[email protected]>
  18. Acked-by: Neil Horman <[email protected]>
  19. Acked-by: Marcelo Ricardo Leitner <[email protected]>
  20. Signed-off-by: David S. Miller <[email protected]>
  21. Signed-off-by: Fabian Grünbichler <[email protected]>
  22. ---
  23. net/sctp/ipv6.c | 10 +++++++---
  24. 1 file changed, 7 insertions(+), 3 deletions(-)
  25. diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
  26. index 5d4c15bf66d2..e35d4f73d2df 100644
  27. --- a/net/sctp/ipv6.c
  28. +++ b/net/sctp/ipv6.c
  29. @@ -326,8 +326,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
  30. final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
  31. bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
  32. - if (!IS_ERR(bdst) &&
  33. - ipv6_chk_addr(dev_net(bdst->dev),
  34. + if (IS_ERR(bdst))
  35. + continue;
  36. +
  37. + if (ipv6_chk_addr(dev_net(bdst->dev),
  38. &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
  39. if (!IS_ERR_OR_NULL(dst))
  40. dst_release(dst);
  41. @@ -336,8 +338,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
  42. }
  43. bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
  44. - if (matchlen > bmatchlen)
  45. + if (matchlen > bmatchlen) {
  46. + dst_release(bdst);
  47. continue;
  48. + }
  49. if (!IS_ERR_OR_NULL(dst))
  50. dst_release(dst);
  51. --
  52. 2.14.2