diff options
author | Neil Horman <nhorman@tuxdriver.com> | 2022-04-25 12:49:25 -0400 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-04-26 07:58:33 +0200 |
commit | 3f4f1dda25a7041d22948e09ec42cf5d4c9b2163 (patch) | |
tree | 7dfbf31c31c4a3e4644072a7b97ffbf52a1abdcb | |
parent | d3c783fa506815dc930a389c906b3b539c710491 (diff) | |
download | libnl-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.c | 4 |
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)); |