From d65c32a7205e679c7fc13f0e4565b13e698ba906 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 18 Aug 2014 15:24:30 +0200 Subject: link: fix memory leaks due to repeated calls to .io_alloc() All the io_alloc() implementation unconditionally allocated new memory, thus leaking memory if called more then once. Fix io_alloc() implementations not to allocate new memory if not needed. This happens for example in link_msg_parser() which first calls rtnl_link_set_type(): #0 macvlan_alloc (link=0x609d50) at route/link/macvlan.c:56 #1 0x00007ffff7b99a78 in rtnl_link_set_type (link=link@entry=0x609d50, type=type@entry=0x609a94 "macvlan") at route/link.c:2233 #2 0x00007ffff7b99c28 in link_msg_parser (ops=, who=, n=, pp=0x7fffffffd870) at route/link.c:547 #3 0x00007ffff7dea109 in nl_cache_parse (ops=0x7ffff7dd8600 , who=0x603338, nlh=0x6098a0, params=0x7fffffffd870) at cache.c:914 #4 0x00007ffff7dea15b in update_msg_parser (msg=, arg=) at cache.c:668 #5 0x00007ffff7def7bf in nl_cb_call (msg=, type=, cb=) at ../include/netlink-private/netlink.h:142 #6 recvmsgs (cb=0x6057a0, sk=0x6034c0) at nl.c:952 #7 nl_recvmsgs_report (sk=sk@entry=0x6034c0, cb=cb@entry=0x6057a0) at nl.c:1003 #8 0x00007ffff7defb79 in nl_recvmsgs (sk=sk@entry=0x6034c0, cb=cb@entry=0x6057a0) at nl.c:1027 #9 0x00007ffff7de9668 in __cache_pickup (sk=0x6034c0, cache=0x603510, param=param@entry=0x7fffffffd870) at cache.c:701 #10 0x00007ffff7dea08d in nl_cache_pickup (sk=, cache=) at cache.c:753 #11 0x0000000000400d56 in main () and later ops->io_parse(): #0 macvlan_alloc (link=0x609d50) at route/link/macvlan.c:56 #1 0x00007ffff7baae9d in macvlan_parse (link=0x609d50, data=, xstats=) at route/link/macvlan.c:79 #2 0x00007ffff7b99c80 in link_msg_parser (ops=, who=, n=, pp=0x7fffffffd870) at route/link.c:567 #3 0x00007ffff7dea109 in nl_cache_parse (ops=0x7ffff7dd8600 , who=0x603338, nlh=0x6098a0, params=0x7fffffffd870) at cache.c:914 #4 0x00007ffff7dea15b in update_msg_parser (msg=, arg=) at cache.c:668 #5 0x00007ffff7def7bf in nl_cb_call (msg=, type=, cb=) at ../include/netlink-private/netlink.h:142 #6 recvmsgs (cb=0x6057a0, sk=0x6034c0) at nl.c:952 #7 nl_recvmsgs_report (sk=sk@entry=0x6034c0, cb=cb@entry=0x6057a0) at nl.c:1003 #8 0x00007ffff7defb79 in nl_recvmsgs (sk=sk@entry=0x6034c0, cb=cb@entry=0x6057a0) at nl.c:1027 #9 0x00007ffff7de9668 in __cache_pickup (sk=0x6034c0, cache=0x603510, param=param@entry=0x7fffffffd870) at cache.c:701 #10 0x00007ffff7dea08d in nl_cache_pickup (sk=, cache=) at cache.c:753 #11 0x0000000000400d56 in main () https://github.com/thom311/libnl/issues/59 Signed-off-by: Thomas Haller --- lib/route/link/can.c | 14 +++++++++----- lib/route/link/ip6tnl.c | 14 +++++++++----- lib/route/link/ipgre.c | 14 +++++++++----- lib/route/link/ipip.c | 14 +++++++++----- lib/route/link/ipvti.c | 14 +++++++++----- lib/route/link/macvlan.c | 10 +++++++--- lib/route/link/sit.c | 14 +++++++++----- lib/route/link/vlan.c | 12 +++++++++--- lib/route/link/vxlan.c | 10 +++++++--- 9 files changed, 77 insertions(+), 39 deletions(-) diff --git a/lib/route/link/can.c b/lib/route/link/can.c index 489119d..4ce554b 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -73,11 +73,15 @@ static int can_alloc(struct rtnl_link *link) { struct can_info *ci; - ci = calloc(1, sizeof(*ci)); - if (!ci) - return -NLE_NOMEM; - - link->l_info = ci; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ci)); + else { + ci = calloc(1, sizeof(*ci)); + if (!ci) + return -NLE_NOMEM; + + link->l_info = ci; + } return 0; } diff --git a/lib/route/link/ip6tnl.c b/lib/route/link/ip6tnl.c index 26f3507..378b8a3 100644 --- a/lib/route/link/ip6tnl.c +++ b/lib/route/link/ip6tnl.c @@ -73,11 +73,15 @@ static int ip6_tnl_alloc(struct rtnl_link *link) { struct ip6_tnl_info *ip6_tnl; - ip6_tnl = calloc(1, sizeof(*ip6_tnl)); - if (!ip6_tnl) - return -NLE_NOMEM; - - link->l_info = ip6_tnl; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ip6_tnl)); + else { + ip6_tnl = calloc(1, sizeof(*ip6_tnl)); + if (!ip6_tnl) + return -NLE_NOMEM; + + link->l_info = ip6_tnl; + } return 0; } diff --git a/lib/route/link/ipgre.c b/lib/route/link/ipgre.c index 3927ab4..2ff03fc 100644 --- a/lib/route/link/ipgre.c +++ b/lib/route/link/ipgre.c @@ -75,11 +75,15 @@ static int ipgre_alloc(struct rtnl_link *link) { struct ipgre_info *ipgre; - ipgre = calloc(1, sizeof(*ipgre)); - if (!ipgre) - return -NLE_NOMEM; - - link->l_info = ipgre; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipgre)); + else { + ipgre = calloc(1, sizeof(*ipgre)); + if (!ipgre) + return -NLE_NOMEM; + + link->l_info = ipgre; + } return 0; } diff --git a/lib/route/link/ipip.c b/lib/route/link/ipip.c index ecf86ad..38f8fef 100644 --- a/lib/route/link/ipip.c +++ b/lib/route/link/ipip.c @@ -62,11 +62,15 @@ static int ipip_alloc(struct rtnl_link *link) { struct ipip_info *ipip; - ipip = calloc(1, sizeof(*ipip)); - if (!ipip) - return -NLE_NOMEM; - - link->l_info = ipip; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipip)); + else { + ipip = calloc(1, sizeof(*ipip)); + if (!ipip) + return -NLE_NOMEM; + + link->l_info = ipip; + } return 0; } diff --git a/lib/route/link/ipvti.c b/lib/route/link/ipvti.c index 71f61c3..b94c573 100644 --- a/lib/route/link/ipvti.c +++ b/lib/route/link/ipvti.c @@ -59,11 +59,15 @@ static int ipvti_alloc(struct rtnl_link *link) { struct ipvti_info *ipvti; - ipvti = calloc(1, sizeof(*ipvti)); - if (!ipvti) - return -NLE_NOMEM; - - link->l_info = ipvti; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipvti)); + else { + ipvti = calloc(1, sizeof(*ipvti)); + if (!ipvti) + return -NLE_NOMEM; + + link->l_info = ipvti; + } return 0; } diff --git a/lib/route/link/macvlan.c b/lib/route/link/macvlan.c index c3eeb3f..b8380aa 100644 --- a/lib/route/link/macvlan.c +++ b/lib/route/link/macvlan.c @@ -55,10 +55,14 @@ static int macvlan_alloc(struct rtnl_link *link) { struct macvlan_info *mvi; - if ((mvi = calloc(1, sizeof(*mvi))) == NULL) - return -NLE_NOMEM; + if (link->l_info) + memset(link->l_info, 0, sizeof(*mvi)); + else { + if ((mvi = calloc(1, sizeof(*mvi))) == NULL) + return -NLE_NOMEM; - link->l_info = mvi; + link->l_info = mvi; + } return 0; } diff --git a/lib/route/link/sit.c b/lib/route/link/sit.c index 0fc1ecd..788bbb8 100644 --- a/lib/route/link/sit.c +++ b/lib/route/link/sit.c @@ -69,11 +69,15 @@ static int sit_alloc(struct rtnl_link *link) { struct sit_info *sit; - sit = calloc(1, sizeof(*sit)); - if (!sit) - return -NLE_NOMEM; - - link->l_info = sit; + if (link->l_info) + memset(link->l_info, 0, sizeof(*sit)); + else { + sit = calloc(1, sizeof(*sit)); + if (!sit) + return -NLE_NOMEM; + + link->l_info = sit; + } return 0; } diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index f977bc4..9dc0d42 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -67,10 +67,16 @@ static int vlan_alloc(struct rtnl_link *link) { struct vlan_info *vi; - if ((vi = calloc(1, sizeof(*vi))) == NULL) - return -NLE_NOMEM; + if (link->l_info) { + vi = link->l_info; + free(vi->vi_egress_qos); + memset(link->l_info, 0, sizeof(*vi)); + } else { + if ((vi = calloc(1, sizeof(*vi))) == NULL) + return -NLE_NOMEM; - link->l_info = vi; + link->l_info = vi; + } return 0; } diff --git a/lib/route/link/vxlan.c b/lib/route/link/vxlan.c index f3e3538..8a9c6e0 100644 --- a/lib/route/link/vxlan.c +++ b/lib/route/link/vxlan.c @@ -91,10 +91,14 @@ static int vxlan_alloc(struct rtnl_link *link) { struct vxlan_info *vxi; - if ((vxi = calloc(1, sizeof(*vxi))) == NULL) - return -NLE_NOMEM; + if (link->l_info) + memset(link->l_info, 0, sizeof(*vxi)); + else { + if ((vxi = calloc(1, sizeof(*vxi))) == NULL) + return -NLE_NOMEM; - link->l_info = vxi; + link->l_info = vxi; + } return 0; } -- cgit v0.12