From f32fba02383f7b1669a13a23d8551e8b33030bb1 Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 8 Jul 2026 23:08:17 +0200 Subject: [PATCH] fix(#2290): use 0777 for per-agent socket dirs in tmpfiles.d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit systemd-tmpfiles d entries adjust mode+owner on existing dirs. Using 0755 root root would stomp live agents' socket dirs (owned by agent uid:gid) on every sync_tmpfiles call, breaking the harness's ability to bind new sockets until host_config rechowns them. Fix: 0777 root root — matches the chmod_socket_dir(0o777) fallback already used by host_config when the agent uid is unavailable. World- writable dirs let the non-root harness bind sockets regardless of who owns the dir. host_config's chown_socket_dir tightens ownership when the agent uid is resolved. Also add missing # Errors doc to priv_client::sync_agent_tmpfiles. --- hive-c0re/src/priv_client.rs | 5 +++++ hive-priv/src/main.rs | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hive-c0re/src/priv_client.rs b/hive-c0re/src/priv_client.rs index c1ed5a10..c8337f21 100644 --- a/hive-c0re/src/priv_client.rs +++ b/hive-c0re/src/priv_client.rs @@ -392,6 +392,11 @@ pub async fn upgrade_agent_subvolume(agent_name: &str) -> Result<()> { /// Write `/etc/tmpfiles.d/hyperhive-agents.conf` for `agents` (logical names, /// e.g. `"atlas"`) and immediately apply it with `systemd-tmpfiles --create`. /// See [`PrivRequest::SyncAgentTmpfiles`] for the full semantics. +/// +/// # Errors +/// +/// Returns an error if the priv socket call fails, if any agent name is +/// invalid, or if `systemd-tmpfiles --create` exits non-zero. pub async fn sync_agent_tmpfiles(agents: &[String]) -> Result<()> { ok(call(&PrivRequest::SyncAgentTmpfiles { agents: agents.to_vec(), diff --git a/hive-priv/src/main.rs b/hive-priv/src/main.rs index 3ad94073..3aee0b2c 100644 --- a/hive-priv/src/main.rs +++ b/hive-priv/src/main.rs @@ -1532,7 +1532,12 @@ async fn sync_agent_tmpfiles(agents: &[String]) -> Result<(String, String)> { // Per-agent dirs. for name in agents { content.push_str(&format!("d {AGENT_RUNTIME_ROOT}/{name} 0755 hive-core hive-core -\n")); - content.push_str(&format!("d {SOCKET_DIR_ROOT}/{name} 0755 root root -\n")); + // 0777: agent harness (non-root uid) must bind sockets here. + // `d` adjusts mode/owner on existing dirs; world-writable matches + // the chmod_socket_dir(0o777) fallback so a runtime re-sync doesn't + // break a live agent's socket dir. host_config's chown_socket_dir + // tightens ownership afterwards when the agent uid is available. + content.push_str(&format!("d {SOCKET_DIR_ROOT}/{name} 0777 root root -\n")); } // Atomic write: write to a tmp file then rename so a concurrent reader