From 465f463ada81f6f745e7e52d27642c64ffc6c225 Mon Sep 17 00:00:00 2001 From: can1357 Date: Tue, 14 Jul 2026 17:56:37 +0200 Subject: [PATCH] fix(python/robomp): ensured omp run directory remained writable for all slots - Added entrypoint setup for `/srv/agent-home/.omp/run` to enforce `omp` group ownership, group-write access, and setgid permissions so any sandbox slot can create or enter daemon state directories. - Updated worker startup to skip generic home normalization on `.omp/run` and added a root-only run-dir preparation pass that reasserts `omp` ownership and writable, setgid permissions before launching subprocesses. --- python/robomp/entrypoint.sh | 11 +++++++++++ python/robomp/src/worker.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/python/robomp/entrypoint.sh b/python/robomp/entrypoint.sh index a6aa67e9e..2bfa00ed8 100755 --- a/python/robomp/entrypoint.sh +++ b/python/robomp/entrypoint.sh @@ -69,6 +69,17 @@ chown -R root:root /srv/agent-home || true find /srv/agent-home -type d -exec chmod 0755 {} + find /srv/agent-home -type f -exec chmod 0644 {} + +# omp registers daemon project presence under ~/.omp/run at startup, nesting +# per-project dirs (daemons//clients) that any slot user must be able to +# create and enter regardless of which slot first made them: setgid + group +# omp keeps the whole tree group-writable (entrypoint umask 0002 carries into +# slot processes, so new entries stay group-writable too). +mkdir -p /srv/agent-home/.omp/run +chgrp -R omp /srv/agent-home/.omp/run +chmod -R g+rwX /srv/agent-home/.omp/run +find /srv/agent-home/.omp/run -type d -exec chmod g+s {} + +chmod 2770 /srv/agent-home/.omp/run + touch /data/robomp.sqlite chown root:root /data/robomp.sqlite chmod 0600 /data/robomp.sqlite diff --git a/python/robomp/src/worker.py b/python/robomp/src/worker.py index af05ff7fd..73a6b5be1 100644 --- a/python/robomp/src/worker.py +++ b/python/robomp/src/worker.py @@ -13,6 +13,7 @@ scheduled onto the parent loop complete (`asyncio.run_coroutine_threadsafe`). from __future__ import annotations import asyncio +import grp import logging import os import shutil @@ -149,6 +150,10 @@ def _stage_agent_home() -> None: chown_to_root = os.geteuid() == 0 for root, dirs, files in os.walk(_AGENT_HOME): root_path = Path(root) + if root_path == _AGENT_HOME / ".omp": + # ~/.omp/run is slot-writable daemon presence state, not template + # config; keep it out of the read-only normalization below. + dirs[:] = [d for d in dirs if d != "run"] try: root_path.chmod(0o755) if chown_to_root: @@ -175,6 +180,36 @@ def _stage_agent_home() -> None: log.warning("Failed to normalize agent home file %s: %s", path, exc) +def _ensure_agent_run_dir() -> None: + """Keep ``~/.omp/run`` writable by every sandbox slot. + + omp registers daemon project presence under ``~/.omp/run`` at startup, + nesting per-project dirs (``daemons//clients``) that any slot user + must be able to create or enter regardless of which slot made them first. + The tree stays group ``omp``, setgid, group-writable; slot subprocesses + spawn with umask 0002 so their entries inherit group write. + """ + if os.geteuid() != 0: + return + run_dir = _AGENT_HOME / ".omp" / "run" + try: + gid = grp.getgrnam("omp").gr_gid + except KeyError: + return + try: + run_dir.mkdir(parents=True, exist_ok=True) + for root, dirs, files in os.walk(run_dir): + root_path = Path(root) + os.chown(root_path, -1, gid) + root_path.chmod(0o2770) + for name in files: + file_path = root_path / name + os.chown(file_path, -1, gid) + file_path.chmod(0o660) + except OSError as exc: + log.warning("Failed to prepare agent run dir %s: %s", run_dir, exc) + + def _build_extra_env(settings: Settings) -> dict[str, str]: """Build the env overlay passed to the omp subprocess. @@ -184,6 +219,7 @@ def _build_extra_env(settings: Settings) -> dict[str, str]: """ del settings # kept for future hooks (model-specific env, etc.) _stage_agent_home() + _ensure_agent_run_dir() env = dict.fromkeys(_SCRUBBED_ENV_KEYS, "") if _AGENT_HOME.is_dir(): env["HOME"] = str(_AGENT_HOME)