ipv6_get_dflt_router() dereferences fib without checking it and returns
fib->leaf, which can also be NULL.  Its three callers then dereference the
result without checking.  A missing default router (for instance on a TUN
interface with no IPv6 configuration) can thus crash pfinet.

Return NULL when fib is NULL, and guard all callers.

* pfinet/options.c (ipv6_get_dflt_router): Return NULL if fib is NULL.
(parse_interface_copy_device, parse_opt, trivfs_append_args): Guard the
router returned by ipv6_get_dflt_router().
---
 pfinet/options.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/pfinet/options.c b/pfinet/options.c
index 5bb8225..46eaf35 100644
--- a/pfinet/options.c
+++ b/pfinet/options.c
@@ -149,7 +149,7 @@ parse_interface_copy_device(struct device *src,
        * if it belongs to it.
        */
       struct rt6_info *rt6i = ipv6_get_dflt_router();
-      if (rt6i->rt6i_dev == src)
+      if (rt6i && rt6i->rt6i_dev == src)
        memcpy (&dst->gateway6, &rt6i->rt6i_gateway, sizeof (struct in6_addr));
 
       /* Search for global address and set it in dst */
@@ -201,7 +201,7 @@ ipv6_get_dflt_router (void)
 
   struct fib6_node *fib = fib6_lookup
     (&ip6_routing_table, &daddr, NULL);
-  return fib->leaf;
+  return fib ? fib->leaf : NULL;
 }
 #endif /* CONFIG_IPV6 */
 
@@ -536,13 +536,13 @@ parse_opt (int opt, char *arg, struct argp_state *state)
        {
          struct rt6_info *rt6i = ipv6_get_dflt_router ();
 
-         if (!gw6_in || rt6i->rt6i_dev != gw6_in->device
+         if (!gw6_in || !rt6i || rt6i->rt6i_dev != gw6_in->device
              || !IN6_ARE_ADDR_EQUAL (&rt6i->rt6i_gateway, &gw6_in->gateway6))
            {
              /* Delete any existing default route on configured devices  */
              for (in = h->interfaces; in < h->interfaces
                   + h->num_interfaces; in++)
-               if (rt6i->rt6i_dev == in->device || gw6_in )
+               if ((rt6i && rt6i->rt6i_dev == in->device) || gw6_in )
                  rt6_purge_dflt_routers (0);
 
              if (gw6_in)
@@ -647,7 +647,7 @@ trivfs_append_args (struct trivfs_control *fsys, char 
**argz, size_t *argz_len)
 
          /* Last not least push --gateway6 option. */
          struct rt6_info *rt6i = ipv6_get_dflt_router ();
-         if(rt6i->rt6i_dev == dev) 
+         if (rt6i && rt6i->rt6i_dev == dev)
            {
              inet_ntop (AF_INET6, &rt6i->rt6i_gateway, addr_buf,
                         INET6_ADDRSTRLEN);
-- 
2.47.3


Reply via email to