]> granicus.if.org Git - libnl/commitdiff
link: fix memory leaks due to repeated calls to .io_alloc()
authorThomas Haller <thaller@redhat.com>
Mon, 18 Aug 2014 13:24:30 +0000 (15:24 +0200)
committerThomas Haller <thaller@redhat.com>
Sun, 12 Oct 2014 17:35:46 +0000 (19:35 +0200)
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=<optimized out>, who=<optimized out>, n=<optimized out>, pp=0x7fffffffd870) at route/link.c:547
    #3  0x00007ffff7dea109 in nl_cache_parse (ops=0x7ffff7dd8600 <rtnl_link_ops>, who=0x603338, nlh=0x6098a0, params=0x7fffffffd870) at cache.c:914
    #4  0x00007ffff7dea15b in update_msg_parser (msg=<optimized out>, arg=<optimized out>) at cache.c:668
    #5  0x00007ffff7def7bf in nl_cb_call (msg=<optimized out>, type=<optimized out>, cb=<optimized out>) 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=<optimized out>, cache=<optimized out>) 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=<optimized out>, xstats=<optimized out>) at route/link/macvlan.c:79
    #2  0x00007ffff7b99c80 in link_msg_parser (ops=<optimized out>, who=<optimized out>, n=<optimized out>, pp=0x7fffffffd870) at route/link.c:567
    #3  0x00007ffff7dea109 in nl_cache_parse (ops=0x7ffff7dd8600 <rtnl_link_ops>, who=0x603338, nlh=0x6098a0, params=0x7fffffffd870) at cache.c:914
    #4  0x00007ffff7dea15b in update_msg_parser (msg=<optimized out>, arg=<optimized out>) at cache.c:668
    #5  0x00007ffff7def7bf in nl_cb_call (msg=<optimized out>, type=<optimized out>, cb=<optimized out>) 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=<optimized out>, cache=<optimized out>) at cache.c:753
    #11 0x0000000000400d56 in main ()

https://github.com/thom311/libnl/issues/59

Signed-off-by: Thomas Haller <thaller@redhat.com>
lib/route/link/can.c
lib/route/link/ip6tnl.c
lib/route/link/ipgre.c
lib/route/link/ipip.c
lib/route/link/ipvti.c
lib/route/link/macvlan.c
lib/route/link/sit.c
lib/route/link/vlan.c
lib/route/link/vxlan.c

index 489119dc54adf1a121f59f1213e017bfe39a1a0e..4ce554bc98ced294f7912addd67a634d5bc2bee9 100644 (file)
@@ -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;
 }
index 26f3507854f9c0f0872f34ab75f68cf8c3d11401..378b8a321985c5df41dd9398610e57572f9b1273 100644 (file)
@@ -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;
 }
index 3927ab41fb31367d79673777fe28e7eac92d4d58..2ff03fc99e8621043348618d8db9a8315e714158 100644 (file)
@@ -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;
 }
index ecf86ad740f3d6e93e54ce24fa33cee1aafbc80c..38f8fef0b4c4d9b7da39bc4ecf581c8eea389ffc 100644 (file)
@@ -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;
 }
index 71f61c36a96dab94cad2afb45e3f7c278349c0e0..b94c573367c2482d372a64d14de4eff74febb166 100644 (file)
@@ -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;
 }
index c3eeb3f20d1e88c5146db224e67277940a51487c..b8380aa7a2da1d9b372aad08b611c8a274330d93 100644 (file)
@@ -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;
 }
index 0fc1ecd97d7ef3c42ff13bb50bde81e48722d862..788bbb84df642ae0f52ba5b3ef4a0de59ea96e92 100644 (file)
@@ -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;
 }
index f977bc41cf01920bbc5a9ffbc90eb72b6e99ae1b..9dc0d425f388a2cbaaa1a192b721549de7fa1871 100644 (file)
@@ -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;
 }
index f3e3538d5c254b38669a5a992774071e1d547779..8a9c6e0bafde46690d4e674eef66497f8e9052cf 100644 (file)
@@ -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;
 }