dhcpcd-discuss

DHCPCD crashed with segfault when trying to add PPP default route

Hiroki Takeuchi

Thu Dec 19 06:11:12 2019

I am using a dhcpcd configuration which adds the destination as default
route (as suggested by the man page):

interface ppp2
metric 123
static ip_address=
destination routers

It has been working fine with DHCPCD 6 until I upgraded to debian/ubuntu
variant of DHCP 7.1.0 and I tracked the error using gdb as it can be
reproduced easily.

#0  get_option (bootp=0x0, bootp_len=0, opt=opt@entry=26,
opt_len=opt_len@entry=0x7ffd99ab97f0, ctx=<optimized out>,
ctx=<optimized out>) at dhcp.c:174
#1  0x0000563e96e22327 in get_option_uint16 (option=26 '\032',
bootp_len=<optimized out>, bootp=<optimized out>, i=<synthetic
pointer>, ctx=<optimized out>) at dhcp.c:314
#2  dhcp_get_mtu (ifp=ifp@entry=0x563e97071220) at dhcp.c:698
#3  0x0000563e96e28312 in inet_routerhostroute (routes=0x7ffd99ab9990,
ifp=0x563e97071220) at ipv4.c:417
#4  inet_getroutes (ctx=ctx@entry=0x7ffd99abaaa0,
routes=routes@entry=0x7ffd99ab9990) at ipv4.c:438
#5  0x0000563e96e194b3 in rt_build (ctx=0x7ffd99abaaa0, af=af@entry=2)
at route.c:515
#6  0x0000563e96e28d4b in ipv4_applyaddr
(arg=arg@entry=0x563e970791b0) at ipv4.c:761
#7  0x0000563e96e234f8 in dhcp_bind (ifp=ifp@entry=0x563e970791b0) at
dhcp.c:2335
#8  0x0000563e96e2381b in dhcp_arp_bind (ifp=0x563e970791b0) at dhcp.c:2446
#9  dhcp_static (ifp=ifp@entry=0x563e97069e80) at dhcp.c:2476
#10 0x0000563e96e27018 in dhcp_start1 (arg=0x563e97069e80,
arg@entry=0x563e970791b0) at dhcp.c:3692
#11 0x0000563e96e279e0 in dhcp_start (ifp=0x563e970791b0) at dhcp.c:3866
#12 0x0000563e96e0e55c in dhcpcd_startinterface (arg=0x563e970791b0)
at dhcpcd.c:921
#13 0x0000563e96e0e881 in reconf_reboot (action=1, argc=3,
argv=0x7ffd99ab9da0, oi=2, ctx=<optimized out>) at dhcpcd.c:1219
#14 0x0000563e96e0f7de in dhcpcd_handleargs (ctx=0x7ffd99abaaa0,
fd=fd@entry=0x563e9704f470, argc=argc@entry=3,
argv=argv@entry=0x7ffd99ab9da0) at dhcpcd.c:1477
#15 0x0000563e96e0c5ba in control_handle_data (arg=0x563e9704f470) at
control.c:143
#16 0x0000563e96e10aab in eloop_start (eloop=0x563e97063630,
signals=0x7ffd99ababa8) at eloop.c:978
#17 0x0000563e96e0b36b in main (argc=<optimized out>, argv=<optimized
out>) at dhcpcd.c:2024

And from my syslog I also noticed a weird log message indicating
requirement of host route in another interface with the PPP interface
destination IP.
dhcpcd[13415]: control command: dhcpcd -n ppp2
dhcpcd[13415]: ppp2: carrier acquired
dhcpcd[13415]: ppp2: IAID 70:70:70:32
dhcpcd[13415]: ppp2: using static address 10.10.10.170/32
dhcpcd[13415]: eno3: router 10.10.10.1 requires a host route
systemd[1]: dhcpcd.service: Main process exited, code=killed, status=11/SEGV
The PPP interface:
23: ppp2: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 qdisc fq_codel
state UNKNOWN group WAN qlen 3
    link/ppp
    inet 10.10.10.170 peer 10.10.10.1/32 scope global ppp2
       valid_lft forever preferred_lft forever

After comparing dhcpcd 6 and dhcpcd 7, and found out that the "routers"
looked-up in  inet_routerhostroute are from multiple interfaces, as opposed
to dhcpcd 6 add_router_host_route is only adding the routes from a single
interface. Hence, I attempted to patch inet_getroutes which apparently
solved this issue.

This is the first time I attempted to modify dhcpcd, sorry if the patch
doesn't match the coding guidelines or principles. Do let me know what you
guys think about this issue and whether there's a better solution to this
issue. Thanks!
diff --git a/src/ipv4.c b/src/ipv4.c
index 7d70825a..55e1416b 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -427,16 +427,19 @@ inet_getroutes(struct dhcpcd_ctx *ctx, struct rt_head *routes)
 	struct interface *ifp;
 	struct rt def;
 	bool have_default;
+	struct rt_head if_routes;
 
 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 		if (!ifp->active)
 			continue;
-		if (inet_dhcproutes(routes, ifp) == -1)
+		TAILQ_INIT(&if_routes);
+		if (inet_dhcproutes(&if_routes, ifp) == -1)
 			return false;
-		if (ipv4ll_subnetroute(routes, ifp) == -1)
+		if (ipv4ll_subnetroute(&if_routes, ifp) == -1)
 			return false;
-		if (inet_routerhostroute(routes, ifp) == -1)
+		if (inet_routerhostroute(&if_routes, ifp) == -1)
 			return false;
+		TAILQ_CONCAT(routes, &if_routes, rt_next);
 	}
 
 	/* If there is no default route, see if we can use an IPv4LL one. */

Follow-Ups:
Re: DHCPCD crashed with segfault when trying to add PPP default routeRoy Marples
Re: DHCPCD crashed with segfault when trying to add PPP default routeRoy Marples
Archive administrator: postmaster@marples.name