Compare commits

..
2 changed files with 2 additions and 46 deletions

View file

@ -72,32 +72,6 @@ the path entry resolves to `/run/wrappers/bin/bin` instead.
hive-c0re restarts. Without it, every restart wipes bind sources and
existing containers can't be started.
### `RestrictAddressFamilies` fails as "Address family not supported by protocol"
A unit whose `RestrictAddressFamilies` omits a family gets `EAFNOSUPPORT`
(errno 97) back from `socket()`. Clients surface that as *"tcp open error:
Address family not supported by protocol"* — the message names the
**protocol** and never the **sandbox**, so it reads like a dead network, a
missing route, or an IPv6 problem.
⇒ On that error, read the unit before you touch the network.
Two things to get right when a daemon needs outbound TCP:
- list `AF_INET` **and** `AF_INET6` — omitting one leaves a client that
works until DNS hands back the other family;
- list `AF_NETLINK` too. glibc's `getaddrinfo` opens a netlink socket to
enumerate local addresses before it returns any, so name resolution
fails without it even when `AF_INET` is allowed.
**The directive is a claim about what the program does, and nothing
re-checks it when the program changes.** A unit that only served a unix
socket when it was written is correct at `[ "AF_UNIX" ]` and silently wrong
the day someone adds an HTTP client. Check the unit in the same commit as
the client — and when narrowing it, prefer a test that derives the required
families from the code (which fails on the *next* client too) over one that
asserts today's list.
### `register_agent` is idempotent
Drops any prior socket task before rebinding. Required so a

View file

@ -508,7 +508,8 @@ in
StateDirectoryMode = "0750";
# Nothing here needs a writable filesystem, real privileges, or a
# view of the rest of the machine.
# view of the rest of the machine; the daemon reads its socket path
# from config and serves.
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
@ -517,27 +518,8 @@ in
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
# `AF_UNIX` for the socket this daemon serves on, plus what its
# outbound clients need: it mints authelia tokens and calls the forge
# over HTTPS (`auth.rs`, `forge.rs`) and reaches the queue over NATS
# (`main.rs`, `status.rs`). `AF_NETLINK` because glibc's
# `getaddrinfo` opens a netlink socket to enumerate local addresses
# before it will return one.
#
# ⚠️ This list is a CLAIM ABOUT WHAT THE DAEMON DOES, so it goes stale
# the moment the daemon grows a client — and it goes stale in the
# worst available way: a blocked family makes `socket()` return
# EAFNOSUPPORT, i.e. "Address family not supported by protocol", so
# the error names the protocol and never the sandbox that refused it.
# This was `AF_UNIX`-only while the daemon merely served its socket;
# all three clients above arrived later, and the restriction was not
# revisited. Add the family when you add the client.
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
};