From: Roy Marples Date: Sun, 17 Mar 2013 13:00:03 +0000 (+0000) Subject: Ensure routes are initialised correctly, fixes #265. X-Git-Tag: v5.99.6~45 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=57c555fbeae84d8056463567119b1e9d3ca2f345;p=thirdparty%2Fdhcpcd.git Ensure routes are initialised correctly, fixes #265. If we fail to malloc any part of a route, clear all the routes. --- diff --git a/dhcp.c b/dhcp.c index 1b1fcd91..e757cbb1 100644 --- a/dhcp.c +++ b/dhcp.c @@ -497,7 +497,6 @@ decode_rfc3442_rt(int dl, const uint8_t *data) cidr = *p++; if (cidr > 32) { ipv4_freeroutes(routes); - free(routes); errno = EINVAL; return NULL; } @@ -506,7 +505,6 @@ decode_rfc3442_rt(int dl, const uint8_t *data) if (rt == NULL) { syslog(LOG_ERR, "%s: %m", __func__); ipv4_freeroutes(routes); - free(routes); return NULL; } TAILQ_INSERT_TAIL(routes, rt, next); @@ -749,6 +747,7 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp) syslog(LOG_ERR, "%s: %m", __func__); return NULL; } + TAILQ_INIT(routes); if (!has_option_mask(ifo->nomask, DHO_STATICROUTE)) p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); else @@ -759,7 +758,8 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp) route = calloc(1, sizeof(*route)); if (route == NULL) { syslog(LOG_ERR, "%s: %m", __func__); - break; + ipv4_freeroutes(routes); + return NULL; } memcpy(&route->dest.s_addr, p, 4); p += 4; @@ -781,7 +781,8 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp) route = calloc(1, sizeof(*route)); if (route == NULL) { syslog(LOG_ERR, "%s: %m", __func__); - break; + ipv4_freeroutes(routes); + return NULL; } memcpy(&route->gate.s_addr, p, 4); p += 4; diff --git a/ipv4.c b/ipv4.c index a7f0f913..02979ca9 100644 --- a/ipv4.c +++ b/ipv4.c @@ -341,6 +341,9 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp) struct rt *r; const struct dhcp_state *s; + if (rt == NULL) /* earlier malloc failed */ + return NULL; + s = D_CSTATE(ifp); if (s->net.s_addr == INADDR_BROADCAST || s->net.s_addr == INADDR_ANY || @@ -350,8 +353,11 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp) return rt; r = malloc(sizeof(*r)); - if (r == NULL) + if (r == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + ipv4_freeroutes(rt); return NULL; + } r->dest.s_addr = s->addr.s_addr & s->net.s_addr; r->net.s_addr = s->net.s_addr; r->gate.s_addr = 0; @@ -394,10 +400,12 @@ massage_host_routes(struct rt_head *rt, const struct interface *ifp) { struct rt *r; - TAILQ_FOREACH(r, rt, next) { - if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr && - r->net.s_addr == INADDR_BROADCAST) - r->gate.s_addr = r->dest.s_addr; + if (rt) { + TAILQ_FOREACH(r, rt, next) { + if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr && + r->net.s_addr == INADDR_BROADCAST) + r->gate.s_addr = r->dest.s_addr; + } } return rt; } @@ -407,12 +415,15 @@ add_destination_route(struct rt_head *rt, const struct interface *iface) { struct rt *r; - if (!(iface->flags & IFF_POINTOPOINT) || + if (rt == NULL || /* failed a malloc earlier probably */ + !(iface->flags & IFF_POINTOPOINT) || !has_option_mask(iface->options->dstmask, DHO_ROUTER)) return rt; + r = malloc(sizeof(*r)); if (r == NULL) { syslog(LOG_ERR, "%s: %m", __func__); + ipv4_freeroutes(rt); return NULL; } r->dest.s_addr = INADDR_ANY; @@ -430,6 +441,9 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp) struct rt *rtp, *rtn; const char *cp, *cp2, *cp3, *cplim; + if (rt == NULL) /* earlier malloc failed */ + return NULL; + TAILQ_FOREACH(rtp, rt, next) { if (rtp->dest.s_addr != INADDR_ANY) continue; @@ -466,7 +480,8 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp) rtn = malloc(sizeof(*rtn)); if (rtn == NULL) { syslog(LOG_ERR, "%s: %m", __func__); - continue; + ipv4_freeroutes(rt); + return NULL; } rtn->dest.s_addr = rtp->gate.s_addr; rtn->net.s_addr = INADDR_BROADCAST; @@ -501,6 +516,8 @@ ipv4_buildroutes(void) dnr = add_router_host_route(dnr, ifp); dnr = add_destination_route(dnr, ifp); } + if (dnr == NULL) /* failed to malloc all new routes */ + continue; TAILQ_FOREACH_SAFE(rt, dnr, next, rtn) { rt->iface = ifp; rt->metric = ifp->metric;