interface-ip: fix memory leak in interface_ip_add_target_route()
authorHans Dedecker <dedeckeh@gmail.com>
Sun, 1 Apr 2018 10:21:38 +0000 (12:21 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Mon, 2 Apr 2018 08:43:52 +0000 (10:43 +0200)
Commit 9c8d781 introduced a memory leak in interface_ip_add_target_route
in case interface_ip_find_addr_target returns true for a given address
by not freeing the previously allocated route.
While at it rework the logic so a host route is only allocated when it's
really required.

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
interface-ip.c

index 1c84d4f8afed8bbe8af9fcc868fb1472b048019d..6726a69bb0d010516a551b47f7e42da3a15f0bf4 100644 (file)
@@ -229,18 +229,12 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
 {
        struct device_route *route, *r_next = NULL;
        bool defaultroute_target = false;
+       union if_addr addr_zero;
        int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in);
 
-       route = calloc(1, sizeof(*route));
-       if (!route)
-               return NULL;
-
-       route->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
-       route->mask = v6 ? 128 : 32;
-       if (memcmp(&route->addr, addr, addrsize) == 0)
+       memset(&addr_zero, 0, sizeof(addr_zero));
+       if (memcmp(&addr_zero, addr, addrsize) == 0)
                defaultroute_target = true;
-       else
-               memcpy(&route->addr, addr, addrsize);
 
        if (iface) {
                /* look for locally addressable target first */
@@ -262,21 +256,27 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
                }
        }
 
-       if (!r_next) {
-               free(route);
+       if (!r_next)
                return NULL;
-       }
 
        iface = r_next->iface;
+       if (defaultroute_target)
+               return iface;
+
+       route = calloc(1, sizeof(*route));
+       if (!route)
+               return NULL;
+
+       route->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
+       route->mask = v6 ? 128 : 32;
+       memcpy(&route->addr, addr, addrsize);
        memcpy(&route->nexthop, &r_next->nexthop, sizeof(route->nexthop));
        route->mtu = r_next->mtu;
        route->metric = r_next->metric;
        route->table = r_next->table;
        route->iface = iface;
-       if (defaultroute_target)
-               free(route);
-       else
-               vlist_add(&iface->host_routes, &route->node, route);
+       vlist_add(&iface->host_routes, &route->node, route);
+
        return iface;
 }