fix(#1845): add safe systemd hardening directives to hive-c0re service

hive-c0re runs as the unprivileged hive-core user and delegates all
privileged operations to hive-priv via a Unix socket. Add the subset of
systemd sandboxing directives that are provably safe without a watched
deploy (no ProtectSystem / RestrictAddressFamilies, which require mapping
the full set of filesystem/network paths first):

- NoNewPrivileges: already unprivileged; no setuid/capability escalation
- PrivateTmp: nix subprocesses use StateDirectory temp paths, not /tmp
- ProtectHome: HOME is /var/lib/hyperhive (StateDirectory), not /home/*
- ProtectKernelTunables: no sysctl writes needed
- ProtectKernelLogs: logs via systemd-journal group, not /dev/kmsg
- ProtectControlGroups: cgroup writes go through hive-priv, not c0re
- RestrictNamespaces: namespace creation goes through hive-priv
- LockPersonality: no personality changes needed
- RestrictRealtime: no real-time scheduling

Follows the same pattern as hive-priv (PrivateTmp + ProtectHome already
present there). Deferred: ProtectSystem=strict + ReadWritePaths +
RestrictAddressFamilies — those need a watched deploy per the #1845 plan
since getting the ReadWritePaths wrong silently breaks runtime I/O.
This commit is contained in:
atlas 2026-07-04 11:37:10 +02:00 committed by mara
commit b3b1c7b288

View file

@ -1094,6 +1094,22 @@ in
RuntimeDirectoryPreserve = "yes";
StateDirectory = "hyperhive";
StateDirectoryMode = "0750";
# Sandboxing. hive-c0re is unprivileged (runs as hive-core, never
# setuid), makes HTTP requests to forge/matrix/Anthropic (keeps INET),
# and delegates all privileged ops to hive-priv via a Unix socket.
# These directives deny the subset of kernel capabilities it
# provably doesn't need without restricting its network or
# filesystem access (ProtectSystem / RestrictAddressFamilies are
# deferred to a follow-up with a watched deploy — see #1845).
NoNewPrivileges = true; # already runs as unprivileged user
PrivateTmp = true; # hive-c0re and its nix subprocesses use tmpfiles under StateDirectory, not /tmp
ProtectHome = true; # HOME = /var/lib/hyperhive (StateDirectory); no /home/* access needed
ProtectKernelTunables = true; # no sysctl writes
ProtectKernelLogs = true; # reads logs via systemd-journal group, not /dev/kmsg
ProtectControlGroups = true; # cgroup writes go through hive-priv, not c0re directly
RestrictNamespaces = true; # namespace creation goes through hive-priv
LockPersonality = true; # no personality changes needed
RestrictRealtime = true; # no real-time scheduling
};
};