From 205986f77ee2a15006acd399c97c14c3c6c1c04d Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 16 Sep 2026 19:41:04 +0200 Subject: [PATCH] swarm-controller: assert socketPath is not in a shared runtime dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The socket is 0666 (nginx needs to connect(2) as a different user), so its directory is the only thing bounding what the gateway's nginx can reach — the crate's README already says so. A unit test pins DEFAULT_SOCKET, but that only catches a developer editing the const; an operator setting the documented socketPath option to a shared dir (notably /run/hyperhive, which holds the host admin socket, or /run/hive) went unenforced. Denylist rather than the general "not any other module's socket dir" form — narrower, but it's what the README names and lands without pulling in other modules' constants. Refs #4208 --- nix/host-modules/swarm-controller.nix | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index 42ac308d..aaf686a2 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -720,6 +720,26 @@ in state directory. ''; } + { + assertion = + let + dir = builtins.dirOf deployCfg.swarm-controller.socketPath; + in + dir != "/run/hyperhive" && dir != "/run/hive" && dir != "/run"; + message = '' + services.hyperhive.deploy.swarm-controller.socketPath puts the + controller socket in + ${builtins.dirOf deployCfg.swarm-controller.socketPath}, a + directory that carries other sockets. + + The controller socket is 0666 and the gateway's nginx is given + its directory, so that directory is the access control. + /run/hyperhive holds host.sock — the host ADMIN socket — and + /run/hive holds the per-agent and priv sockets. Give the + controller a directory of its own (the default, + /run/swarm-controller, is one). + ''; + } ]; systemd.services.swarm-controller = {