]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Fix a memory NULL deference when freeing static routes at exit.
authorRoy Marples <roy@marples.name>
Sun, 28 Jul 2019 20:14:41 +0000 (21:14 +0100)
committerRoy Marples <roy@marples.name>
Sun, 28 Jul 2019 20:14:41 +0000 (21:14 +0100)
This is less effort than changing the options API to work with
an interface object rather than an interface name.

src/if-options.c
src/route.c

index d2c82a3a816a2a294eb2c9284cf86605db30a105..04e519eee1c437133e94e8ae824b822c456e6fc2 100644 (file)
@@ -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);
 }
index a0bb2a1c8ae45daa10cf48bf539a5aef15dafa11..526e4c599620d303c7e41cf5f50fb35fa3d5f32e 100644 (file)
@@ -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);