fix(#946): drop hive-priv self-bind fallback (require socket activation) + clarify child-state rw is intentional
This commit is contained in:
parent
f751c4495f
commit
58b5434466
3 changed files with 40 additions and 36 deletions
|
|
@ -57,9 +57,14 @@ async fn main() -> Result<()> {
|
|||
}
|
||||
|
||||
fn socket_listener() -> Result<UnixListener> {
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
// Socket activation: systemd passes the socket as fd 3 when
|
||||
// LISTEN_FDS >= 1 and LISTEN_PID matches our pid.
|
||||
// hive-priv is ALWAYS socket-activated: systemd's `hive-priv.socket`
|
||||
// unit binds `/run/hive/priv.sock` (SocketGroup=hive-core, mode 0660)
|
||||
// and passes it as fd 3 via LISTEN_FDS. We require that — there is
|
||||
// intentionally no self-bind fallback, so dev and prod take the exact
|
||||
// same path. (The old fallback re-bound the socket itself as root's
|
||||
// primary group, never `hive-core`, so a hive-core client couldn't
|
||||
// connect the way the socket unit's grant intends; dropping it removes
|
||||
// that dev/prod divergence.)
|
||||
let listen_fds: Option<i32> = std::env::var("LISTEN_FDS")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok());
|
||||
|
|
@ -67,35 +72,27 @@ fn socket_listener() -> Result<UnixListener> {
|
|||
.ok()
|
||||
.and_then(|s| s.parse().ok());
|
||||
|
||||
if let (Some(n), Some(p)) = (listen_fds, listen_pid)
|
||||
&& n >= 1
|
||||
&& p == std::process::id()
|
||||
{
|
||||
// SAFETY: systemd has passed us a ready UnixListener on fd 3.
|
||||
let std_listener = unsafe {
|
||||
use std::os::unix::io::FromRawFd;
|
||||
std::os::unix::net::UnixListener::from_raw_fd(3)
|
||||
};
|
||||
std_listener
|
||||
.set_nonblocking(true)
|
||||
.context("set socket non-blocking")?;
|
||||
let listener =
|
||||
tokio::net::UnixListener::from_std(std_listener).context("wrap systemd socket")?;
|
||||
tracing::info!("using systemd-activated socket");
|
||||
return Ok(listener);
|
||||
let activated =
|
||||
matches!(listen_fds, Some(n) if n >= 1) && listen_pid == Some(std::process::id());
|
||||
if !activated {
|
||||
bail!(
|
||||
"hive-priv requires systemd socket activation (expected LISTEN_FDS>=1 + \
|
||||
LISTEN_PID=<self> for {PRIV_SOCK}); run it via the hive-priv.socket unit, \
|
||||
not directly"
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback: bind the socket ourselves.
|
||||
let path = Path::new(PRIV_SOCK);
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent).with_context(|| format!("create {}", parent.display()))?;
|
||||
}
|
||||
let _ = std::fs::remove_file(path);
|
||||
let listener = UnixListener::bind(path).with_context(|| format!("bind {PRIV_SOCK}"))?;
|
||||
// Mode 0660: only the hive-core group can connect.
|
||||
std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o660))
|
||||
.context("chmod priv.sock")?;
|
||||
tracing::info!(path = PRIV_SOCK, "bound priv socket");
|
||||
// SAFETY: systemd has passed us a ready UnixListener on fd 3.
|
||||
let std_listener = unsafe {
|
||||
use std::os::unix::io::FromRawFd;
|
||||
std::os::unix::net::UnixListener::from_raw_fd(3)
|
||||
};
|
||||
std_listener
|
||||
.set_nonblocking(true)
|
||||
.context("set socket non-blocking")?;
|
||||
let listener =
|
||||
tokio::net::UnixListener::from_std(std_listener).context("wrap systemd socket")?;
|
||||
tracing::info!("using systemd-activated socket");
|
||||
Ok(listener)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue