From fcb17db4ab1ac1de293676864708fdc5dc4a0e34 Mon Sep 17 00:00:00 2001 From: joshsiv-mulga Date: Tue, 19 May 2026 13:16:56 +1000 Subject: [PATCH] fix(daemon): use numeric uid/gid when creating tap to avoid silent skip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit user.Current() can return an error under hardened systemd units / static builds, causing the user/group flags to be silently dropped on `ip tuntap add` and leaving the tap root-owned. The child QEMU then runs as spinifex-daemon, fails the tun_chr_open owner check, and exits with "could not configure /dev/net/tun: Operation not permitted" before writing its PID file — the LB microvm never boots and the load balancer sticks in failed/provisioning state. Reproduced in E2E nightly cell-17 (single/static/debian-13/tofu-examples) run 26047315237 on the nginx-alb workbook at commit 4ae2a4a (the microvm-elbv2 merge that introduced the prior user.Current() fix). Pass os.Geteuid() and os.Getegid() numerically instead — always available, no NSS lookup, no silent fallthrough. Closes mulga-siv-110 --- spinifex/daemon/network.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spinifex/daemon/network.go b/spinifex/daemon/network.go index 92acca76d..9367194a5 100644 --- a/spinifex/daemon/network.go +++ b/spinifex/daemon/network.go @@ -6,8 +6,8 @@ import ( "net" "os" "os/exec" - "os/user" "sort" + "strconv" "strings" "github.com/mulgadc/spinifex/spinifex/utils" @@ -55,12 +55,14 @@ func (p *OVSNetworkPlumber) SetupTap(spec vm.TapSpec) error { // (drivers/net/tun.c: tun_chr_open + TUNSETIFF perm check). Without the // `user` flag the tap defaults to root:root and qemu's TUNSETIFF fails // with EPERM ("could not configure /dev/net/tun: Operation not permitted"). - // Root daemons skip this — they have CAP_NET_ADMIN ambient. + // Pass numeric uid/gid directly — user.Current() can fail silently under + // hardened systemd units / static builds, dropping the flags and leaving + // the tap root-owned (LB microvm in cell-17/tofu-examples). Numeric values + // always work and skip the NSS lookup. Root daemons skip this — they have + // CAP_NET_ADMIN ambient. addArgs := []string{"tuntap", "add", "dev", spec.Name, "mode", "tap"} - if os.Geteuid() != 0 { - if u, err := user.Current(); err == nil { - addArgs = append(addArgs, "user", u.Username, "group", u.Gid) - } + if uid := os.Geteuid(); uid != 0 { + addArgs = append(addArgs, "user", strconv.Itoa(uid), "group", strconv.Itoa(os.Getegid())) } if out, err := sudoCommand("ip", addArgs...).CombinedOutput(); err != nil { return fmt.Errorf("create tap %s: %s: %w", spec.Name, strings.TrimSpace(string(out)), err)