From 2d8c0d24f206a3eb32cd86653fa6e70f8018929c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 24 Apr 2014 15:08:31 +0200 Subject: [PATCH] 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. --- nixos/modules/services/networking/dhcpcd.nix | 6 ++--- .../networking/dhcpcd/check-interface.patch | 24 +++++++++++++++++++ pkgs/tools/networking/dhcpcd/default.nix | 2 +- pkgs/tools/networking/dhcpcd/reload.patch | 22 +++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 pkgs/tools/networking/dhcpcd/check-interface.patch create mode 100644 pkgs/tools/networking/dhcpcd/reload.patch diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index ce9b4a3b15d..757340b3c2c 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -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"; }; }; diff --git a/pkgs/tools/networking/dhcpcd/check-interface.patch b/pkgs/tools/networking/dhcpcd/check-interface.patch new file mode 100644 index 00000000000..2b732b740ad --- /dev/null +++ b/pkgs/tools/networking/dhcpcd/check-interface.patch @@ -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))) { + diff --git a/pkgs/tools/networking/dhcpcd/default.nix b/pkgs/tools/networking/dhcpcd/default.nix index d247dbe38aa..40f6538750f 100644 --- a/pkgs/tools/networking/dhcpcd/default.nix +++ b/pkgs/tools/networking/dhcpcd/default.nix @@ -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 ]; diff --git a/pkgs/tools/networking/dhcpcd/reload.patch b/pkgs/tools/networking/dhcpcd/reload.patch new file mode 100644 index 00000000000..0ecb75a4476 --- /dev/null +++ b/pkgs/tools/networking/dhcpcd/reload.patch @@ -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; +