From db8937f9e9e5f1f341d423de69bc1334184783ca Mon Sep 17 00:00:00 2001 From: archipelago Date: Fri, 7 Aug 2026 19:59:48 -0400 Subject: [PATCH] fix(container): root stat fallback makes volume ownership drift authoritative The direct metadata read can be denied in the service's rootless context even when the directory is already correctly owned, which kept the reconciler calling sudo chown on the same Postgres volume every minute. A root fallback gives the guard a reliable answer on deployed nodes while remaining much cheaper than a recursive chown. Co-Authored-By: Claude --- .../src/container/prod_orchestrator.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/core/archipelago/src/container/prod_orchestrator.rs b/core/archipelago/src/container/prod_orchestrator.rs index 9d773f8f..37ae6330 100644 --- a/core/archipelago/src/container/prod_orchestrator.rs +++ b/core/archipelago/src/container/prod_orchestrator.rs @@ -291,6 +291,14 @@ async fn chown_for_rootless_container(uid_gid: &str, path: &str) -> Result<()> { if ownership_already_correct(path, &host_uid_gid) { return Ok(()); } + // Some rootless-service contexts can read the directory entry but fail + // Rust's metadata lookup through an ACL/namespace boundary. Ask the + // host's root view before falling through to an expensive `chown -R`. + // This is still cheap compared with recursively walking Postgres on every + // reconcile and makes the drift gate authoritative on deployed nodes. + if ownership_already_correct_from_host(path, &host_uid_gid).await { + return Ok(()); + } if uid > 0 && uid < 100_000 { let output = tokio::process::Command::new("podman") @@ -353,6 +361,17 @@ fn ownership_already_correct(path: &str, host_uid_gid: &str) -> bool { md.uid() == uid && md.gid() == gid } +async fn ownership_already_correct_from_host(path: &str, host_uid_gid: &str) -> bool { + let Ok(out) = tokio::process::Command::new("sudo") + .args(["stat", "-c", "%u:%g", path]) + .output() + .await + else { + return false; + }; + out.status.success() && String::from_utf8_lossy(&out.stdout).trim() == host_uid_gid +} + /// `(container-id, mount-dest)` pairs whose in-container chown returned a hard, /// permanent failure (e.g. "Operation not permitted" on a mount that can't be /// re-owned from inside the userns). Remembered for the life of the process so