dhcpcd: Fix segfaults

This fixes several problems in the dhcpcd service:

* A segfault during startup, due to a race with udev (dhcpcd would get
  an ADD event from udev, causing it to re-add an interface that it
  already had, leading to a segfault later on).

* A hang/segfault processing "dhcpcd rebind" (which NixOS calls after
  waking up from suspend).

Also, add "lo" to the list of ignored interfaces. It usually ignores
"lo", but apparently not when it gets an ADD event from udev.
This commit is contained in:
Eelco Dolstra 2014-04-24 15:08:31 +02:00
parent 25af3671f9
commit 2d8c0d24f2
4 changed files with 49 additions and 5 deletions

View file

@ -36,7 +36,7 @@ let
# Ethernet cards used for bridging. Likewise for vif* and tap*
# (Xen) and virbr* and vnet* (libvirt) and c-* and ctmp-* (NixOS
# containers).
denyinterfaces ${toString ignoredInterfaces} peth* vif* tap* tun* virbr* vnet* vboxnet* c-* ctmp-*
denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* c-* ctmp-*
${config.networking.dhcpcd.extraConfig}
'';
@ -98,7 +98,6 @@ in
{ description = "DHCP Client";
wantedBy = [ "network.target" ];
after = [ "systemd-udev-settle.service" ]; # FIXME
# Stopping dhcpcd during a reconfiguration is undesirable
# because it brings down the network interfaces configured by
@ -112,9 +111,8 @@ in
serviceConfig =
{ Type = "forking";
PIDFile = "/run/dhcpcd.pid";
ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --config ${dhcpcdConf}";
ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --quiet --config ${dhcpcdConf}";
ExecReload = "${dhcpcd}/sbin/dhcpcd --rebind";
StandardError = "null";
Restart = "always";
};
};

View file

@ -0,0 +1,24 @@
Index: dhcpcd.c
==================================================================
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -747,14 +747,14 @@
if (ifp->hwlen != 0)
memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
} else {
TAILQ_REMOVE(ifs, ifp, next);
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
- }
- if (action == 1) {
- init_state(ifp, ctx->argc, ctx->argv);
- start_interface(ifp);
+ if (action == 1) {
+ init_state(ifp, ctx->argc, ctx->argv);
+ start_interface(ifp);
+ }
}
}
/* Free our discovered list */
while ((ifp = TAILQ_FIRST(ifs))) {

View file

@ -8,7 +8,7 @@ stdenv.mkDerivation rec {
sha256 = "1v2m5wdr6x5cz6i0n1y63am9dhj5j7ylrk717scjgwwjdbq1x75n";
};
patches = [ ./lxc_ro_promote_secondaries.patch ];
patches = [ ./lxc_ro_promote_secondaries.patch ./reload.patch ./check-interface.patch ];
buildInputs = [ pkgconfig udev ];

View file

@ -0,0 +1,22 @@
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -143,16 +143,18 @@
if (ctx->ifac) {
for (ctx->ifac--; ctx->ifac >= 0; ctx->ifac--)
free(ctx->ifav[ctx->ifac]);
free(ctx->ifav);
ctx->ifav = NULL;
+ ctx->ifac = 0;
}
if (ctx->ifdc) {
for (ctx->ifdc--; ctx->ifdc >= 0; ctx->ifdc--)
free(ctx->ifdv[ctx->ifdc]);
free(ctx->ifdv);
ctx->ifdv = NULL;
+ ctx->ifdc = 0;
}
#ifdef INET
if (ctx->dhcp_opts) {
for (opt = ctx->dhcp_opts;