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