From: Roy Marples Date: Sun, 28 Jul 2019 20:14:41 +0000 (+0100) Subject: Fix a memory NULL deference when freeing static routes at exit. X-Git-Tag: v8.0.2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06367b169002c027e190797ff3f7d6ff6db5e235;p=thirdparty%2Fdhcpcd.git Fix a memory NULL deference when freeing static routes at exit. This is less effort than changing the options API to work with an interface object rather than an interface name. --- diff --git a/src/if-options.c b/src/if-options.c index d2c82a3a..04e519ee 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -2611,73 +2611,88 @@ void free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo) { size_t i; +#ifdef RT_FREE_ROUTE_TABLE + struct rt *rt; +#endif struct dhcp_opt *opt; struct vivco *vo; #ifdef AUTH struct token *token; #endif - if (ifo) { - if (ifo->environ) { - i = 0; - while (ifo->environ[i]) - free(ifo->environ[i++]); - free(ifo->environ); - } - if (ifo->config) { - i = 0; - while (ifo->config[i]) - free(ifo->config[i++]); - free(ifo->config); - } - rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); - if (ifo->script != default_script) - free(ifo->script); - free(ifo->arping); - free(ifo->blacklist); - free(ifo->fallback); + if (ifo == NULL) + return; - for (opt = ifo->dhcp_override; - ifo->dhcp_override_len > 0; - opt++, ifo->dhcp_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->dhcp_override); - for (opt = ifo->nd_override; - ifo->nd_override_len > 0; - opt++, ifo->nd_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->nd_override); - for (opt = ifo->dhcp6_override; - ifo->dhcp6_override_len > 0; - opt++, ifo->dhcp6_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->dhcp6_override); - for (vo = ifo->vivco; - ifo->vivco_len > 0; - vo++, ifo->vivco_len--) - free(vo->data); - free(ifo->vivco); - for (opt = ifo->vivso_override; - ifo->vivso_override_len > 0; - opt++, ifo->vivso_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->vivso_override); + if (ifo->environ) { + i = 0; + while (ifo->environ[i]) + free(ifo->environ[i++]); + free(ifo->environ); + } + if (ifo->config) { + i = 0; + while (ifo->config[i]) + free(ifo->config[i++]); + free(ifo->config); + } + +#ifdef RT_FREE_ROUTE_TABLE + /* Stupidly, we don't know the interface when creating the options. + * As such, make sure each route has one so they can goto the + * free list. */ + RB_TREE_FOREACH(rt, &ifo->routes) { + if (rt->rt_ifp == NULL) + rt->rt_ifp = TAILQ_FIRST(ctx->ifaces); + } +#endif + rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); + + if (ifo->script != default_script) + free(ifo->script); + free(ifo->arping); + free(ifo->blacklist); + free(ifo->fallback); + + for (opt = ifo->dhcp_override; + ifo->dhcp_override_len > 0; + opt++, ifo->dhcp_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->dhcp_override); + for (opt = ifo->nd_override; + ifo->nd_override_len > 0; + opt++, ifo->nd_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->nd_override); + for (opt = ifo->dhcp6_override; + ifo->dhcp6_override_len > 0; + opt++, ifo->dhcp6_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->dhcp6_override); + for (vo = ifo->vivco; + ifo->vivco_len > 0; + vo++, ifo->vivco_len--) + free(vo->data); + free(ifo->vivco); + for (opt = ifo->vivso_override; + ifo->vivso_override_len > 0; + opt++, ifo->vivso_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->vivso_override); #if defined(INET6) && !defined(SMALL) - for (; ifo->ia_len > 0; ifo->ia_len--) - free(ifo->ia[ifo->ia_len - 1].sla); + for (; ifo->ia_len > 0; ifo->ia_len--) + free(ifo->ia[ifo->ia_len - 1].sla); #endif - free(ifo->ia); + free(ifo->ia); #ifdef AUTH - while ((token = TAILQ_FIRST(&ifo->auth.tokens))) { - TAILQ_REMOVE(&ifo->auth.tokens, token, next); - if (token->realm_len) - free(token->realm); - free(token->key); - free(token); - } -#endif - free(ifo); + while ((token = TAILQ_FIRST(&ifo->auth.tokens))) { + TAILQ_REMOVE(&ifo->auth.tokens, token, next); + if (token->realm_len) + free(token->realm); + free(token->key); + free(token); } +#endif + free(ifo); } diff --git a/src/route.c b/src/route.c index a0bb2a1c..526e4c59 100644 --- a/src/route.c +++ b/src/route.c @@ -392,8 +392,10 @@ rt_free(struct rt *rt) struct dhcpcd_ctx *ctx; assert(rt != NULL); - assert(rt->rt_ifp != NULL); - assert(rt->rt_ifp->ctx != NULL); + if (rt->rt_ifp == NULL) { + free(rt); + return; + } ctx = rt->rt_ifp->ctx; rb_tree_insert_node(&ctx->froutes, rt);