summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2022-04-25 12:49:25 -0400
committerThomas Haller <thaller@redhat.com>2022-04-26 07:58:33 +0200
commit3f4f1dda25a7041d22948e09ec42cf5d4c9b2163 (patch)
tree7dfbf31c31c4a3e4644072a7b97ffbf52a1abdcb
parentd3c783fa506815dc930a389c906b3b539c710491 (diff)
downloadlibnl-3f4f1dda25a7041d22948e09ec42cf5d4c9b2163.tar.gz
xfrm/sa: fix reference counters of sa selector addresses
valgrind reported this memory leak to me in testing an application that I'm building: ==1807969== 24 bytes in 1 blocks are definitely lost in loss record 2 of 12 ==1807969== at 0x4849464: calloc (vg_replace_malloc.c:1328) ==1807969== by 0x160F2F: nl_addr_alloc (addr.c:184) ==1807969== by 0x160F2F: nl_addr_build (addr.c:215) ==1807969== by 0x15CEF1: xfrmnl_sa_parse (sa.c:693) ==1807969== by 0x18F95D: parse_sa (xfrm_monitor.c:82) ==1807969== by 0x18FC5A: parse_nlmsg (xfrm_monitor.c:170) ==1807969== by 0x18FC5A: xfrm_cb (xfrm_monitor.c:181) ==1807969== by 0x169D21: nl_cb_call (netlink.h:138) ==1807969== by 0x169D21: recvmsgs (nl.c:868) ==1807969== by 0x16A42C: nl_recvmsgs_report (nl.c:1051) ==1807969== by 0x16A42C: nl_recvmsgs (nl.c:1075) ==1807969== by 0x16A42C: nl_recvmsgs_default (nl.c:1089) ==1807969== by 0x18FD6F: monitor_xfrm (xfrm_monitor.c:233) ==1807969== by 0x49D8B19: start_thread (pthread_create.c:443) ==1807969== by 0x4A5C8F3: clone (clone.S:100) when calling xfrmnl_sa_parse, we accidentally get a refcount of 2 on the selector source and destination addresses. The nl_addr_build calls for these addresses set the count to one, and the subsequent calls to xfrmnl_sel_set_[s|d]addr increase the reference count to two. One of the references is dropped when we call xfrmnl_sa_put, which calls down through xfrmnl_sa_free_data->xfrmnl_sel_put->nl_addr_put(), but the other reference count is leaked, leading to the above leak of both the saddr and daddr pointers. Not sure if this is the ideal fix, but it works for me, we just drop the refrence count incremented by the call to set_[s|d]addr. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> https://github.com/thom311/libnl/pull/312
-rw-r--r--lib/xfrm/sa.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index 5567eb74..a8bbced3 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -722,6 +722,8 @@ int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result)
addr = nl_addr_build (sa_info->sel.family, &sa_info->sel.daddr.a6, sizeof (sa_info->sel.daddr.a6));
nl_addr_set_prefixlen (addr, sa_info->sel.prefixlen_d);
xfrmnl_sel_set_daddr (sa->sel, addr);
+ /* Drop the reference count from the above set operation */
+ nl_addr_put(addr);
xfrmnl_sel_set_prefixlen_d (sa->sel, sa_info->sel.prefixlen_d);
if (sa_info->sel.family == AF_INET)
@@ -730,6 +732,8 @@ int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result)
addr = nl_addr_build (sa_info->sel.family, &sa_info->sel.saddr.a6, sizeof (sa_info->sel.saddr.a6));
nl_addr_set_prefixlen (addr, sa_info->sel.prefixlen_s);
xfrmnl_sel_set_saddr (sa->sel, addr);
+ /* Drop the reference count from the above set operation */
+ nl_addr_put(addr);
xfrmnl_sel_set_prefixlen_s (sa->sel, sa_info->sel.prefixlen_s);
xfrmnl_sel_set_dport (sa->sel, ntohs(sa_info->sel.dport));