ruvnet/RuView · error

EIO

EIO

Error message

veil: genl_connect failed

What it means

Byte-identical copy of the privshield daemon inside the standalone wifi-veil workspace. `genl_connect()` attaches the socket to NETLINK_GENERIC; any failure is flattened to `-EIO` here. Real causes are environmental — AF_NETLINK blocked by seccomp/container policy, missing privileges in a user namespace, or fd exhaustion — rather than a daemon bug.

Source

Thrown at wifi-veil/firmware/openwrt/veil_shieldd.c:75

    size_t          passes; /* Givens passes                                */
    volatile sig_atomic_t running;
};

static struct veil_ctx g_ctx;

static void on_signal(int sig) { (void)sig; g_ctx.running = 0; }

/* ---------------------------------------------------------------------- */
/* nl80211 bring-up — all REAL libnl-genl-3 API names.                     */
/* ---------------------------------------------------------------------- */
static int veil_nl_connect(struct veil_ctx *c) {
    c->sock = nl_socket_alloc();
    if (!c->sock) {
        fprintf(stderr, "veil: nl_socket_alloc failed\n");
        return -ENOMEM;
    }
    if (genl_connect(c->sock)) {
        fprintf(stderr, "veil: genl_connect failed\n");
        return -EIO;
    }
    c->family = genl_ctrl_resolve(c->sock, "nl80211");
    if (c->family < 0) {
        fprintf(stderr, "veil: genl_ctrl_resolve(nl80211) failed: %d\n",
                c->family);
        return c->family;
    }
    /* Observe MLME events (auth/assoc, and — where the driver forwards them —
     * action-frame notifications). Real multicast group name is "mlme". */
    int grp = genl_ctrl_resolve_grp(c->sock, "nl80211", "mlme");
    if (grp >= 0) {
        (void)nl_socket_add_membership(c->sock, grp);
    }
    return 0;
}

/* ---------------------------------------------------------------------- */

View on GitHub (pinned to 4685618388)

Solutions

  1. Run with host network namespace and CAP_NET_ADMIN (`--net=host --cap-add NET_ADMIN`).
  2. Loosen `RestrictAddressFamilies` to include `AF_NETLINK` in the unit file, or raise fd limits.
  3. Cross-check with `iw list` on the same host: if that also fails, the environment blocks netlink, not the daemon.

Example fix

# before
systemd-run ./veil_shieldd -i 2            # veil: genl_connect failed
# after
# unit file: RestrictAddressFamilies=AF_UNIX AF_NETLINK
systemctl restart veil_shieldd
Defensive patterns

Strategy: validation

Validate before calling

static int netlink_available(void) {
    struct nl_sock *t = nl_socket_alloc();
    if (!t) return -1;
    int rc = genl_connect(t);
    nl_socket_free(t);
    return rc == 0 ? 0 : -1;
}

Try / catch

int rc = veil_nl_connect(&g_ctx);
if (rc == -EIO) {
    fprintf(stderr, "veil: netlink blocked — need host netns + CAP_NET_ADMIN\n");
    exit(rc);
}

Prevention

When it happens

Trigger: Container run without `--net=host`/CAP_NET_ADMIN; restrictive `RestrictAddressFamilies=AF_UNIX` in a systemd unit; EMFILE from fd leaks; kernel without generic netlink.

Common situations: CI or laptop smoke tests of the wifi-veil build; hardened service units; chroots without netlink devices.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/9929a801ad30cc0a. Report an issue: GitHub.