Files
guix-router/packages/patches/netifd-popen-bin-sh.patch
ssmithxandClaude Opus 5.5 b2c2d79b19 netifd takes the WAN: base-files shell lib, udhcpc, dhcp proto
- openwrt-base-files: functions.sh, functions/{network,ipv4,system,
  uci-defaults}.sh and uci's config/uci.sh, with store paths.
- netifd: install proto/dhcp.sh + dhcp.script (busybox udhcpc, store
  paths, busybox ash shebangs); patch handler discovery to run /bin/sh
  itself, since cross-built glibc's popen() execs an x86-64 bash.
- netifd-configuration external-devices: attach wpa_supplicant's wlan0
  to wan over ubus (netifd won't adopt WiFi netdevs from config); PATH
  for protocol scripts; /var/state.
- rpi4.scm: dhcpcd removed; netifd writes /etc/resolv.conf.
- Tested in network namespaces (x86, then on the Pi), then cold boot of
  generation 13: lease, route, DNS, clock sync, LAN clients routed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:48:11 -04:00

88 lines
1.7 KiB
Diff

diff --git a/handler.c b/handler.c
index 5eb3132..7aafe04 100644
--- a/handler.c
+++ b/handler.c
@@ -16,6 +16,8 @@
#include <glob.h>
#include <fcntl.h>
#include <stdio.h>
+#include <unistd.h>
+#include <sys/wait.h>
#include "netifd.h"
#include "system.h"
@@ -61,6 +63,55 @@ out:
return ret;
}
+/*
+ * popen()/pclose() replacement that runs /bin/sh itself. On a Guix system
+ * cross-built from x86_64, glibc's popen() execs the build host's static bash
+ * (an x86_64 binary), so it fails on the target and no handlers would load.
+ */
+static pid_t dump_pid = -1;
+
+static FILE *
+netifd_popen_sh(const char *cmd)
+{
+ int fds[2];
+ FILE *f;
+
+ if (pipe(fds))
+ return NULL;
+
+ dump_pid = fork();
+ if (dump_pid < 0) {
+ close(fds[0]);
+ close(fds[1]);
+ return NULL;
+ }
+
+ if (!dump_pid) {
+ close(fds[0]);
+ if (fds[1] != STDOUT_FILENO) {
+ dup2(fds[1], STDOUT_FILENO);
+ close(fds[1]);
+ }
+ execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
+ _exit(127);
+ }
+
+ close(fds[1]);
+ f = fdopen(fds[0], "r");
+ if (!f)
+ close(fds[0]);
+ return f;
+}
+
+static void
+netifd_pclose_sh(FILE *f)
+{
+ fclose(f);
+ if (dump_pid > 0)
+ waitpid(dump_pid, NULL, 0);
+ dump_pid = -1;
+}
+
static void
netifd_init_script_handler(const char *script, json_object *obj, script_dump_cb cb)
{
@@ -152,7 +203,7 @@ netifd_parse_script_handler(const char *name, script_dump_cb cb)
cmd = alloca(strlen(name) + 1 + sizeof(DUMP_SUFFIX));
sprintf(cmd, "%s" DUMP_SUFFIX, name);
- f = popen(cmd, "r");
+ f = netifd_popen_sh(cmd);
if (!f)
return;
@@ -183,7 +234,7 @@ netifd_parse_script_handler(const char *name, script_dump_cb cb)
if (tok)
json_tokener_free(tok);
- pclose(f);
+ netifd_pclose_sh(f);
}
static void