fix: chown staged mount sources to container user
Config-profile and git mounts staged under instance_dir were created by the API process (root), so when bind-mounted over ~/.config the container user could not write. Recursively chown staged sources to the resolved container uid/gid before compose up. Quality gates: python3 -m py_compile passed; ruff/pytest skipped (test tooling not available in this shell, helper smoke tested with a temporary directory).
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Tool instance service functions."""
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import glob as glob_module
|
||||
import logging
|
||||
import os
|
||||
@@ -71,6 +72,41 @@ from src.auth.dependencies import _get_owned_project, _get_user
|
||||
logger = logging.getLogger(__name__)
|
||||
_event_bus = InstanceEventBus()
|
||||
|
||||
|
||||
def _chown_path(path: str, uid: int, gid: int) -> None:
|
||||
"""Recursively chown a path, suppressing permission errors."""
|
||||
try:
|
||||
if os.path.isdir(path):
|
||||
for root, dirs, files in os.walk(path):
|
||||
for name in dirs + files:
|
||||
full = os.path.join(root, name)
|
||||
with contextlib.suppress(OSError):
|
||||
os.chown(full, uid, gid)
|
||||
with contextlib.suppress(OSError):
|
||||
os.chown(path, uid, gid)
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to chown %s to %s:%s: %s", path, uid, gid, exc)
|
||||
|
||||
|
||||
def _chown_staged_mounts(
|
||||
extra_volumes: list[dict],
|
||||
instance_dir: str,
|
||||
uid: int,
|
||||
gid: int,
|
||||
) -> None:
|
||||
"""Recursively chown staged mount sources to the container user.
|
||||
|
||||
Config-profile mounts, git mounts, and SSH key mounts are staged under
|
||||
instance_dir by the API process (root). Without this, the container
|
||||
user cannot write into bind-mounted directories such as ~/.config.
|
||||
"""
|
||||
for vol in extra_volumes:
|
||||
source = vol.get("source", "")
|
||||
if not source or not source.startswith(instance_dir):
|
||||
continue
|
||||
_chown_path(source, uid, gid)
|
||||
|
||||
|
||||
async def resolve_git_mounts(
|
||||
session: AsyncSession,
|
||||
resolved: ResolvedProfile,
|
||||
@@ -1308,6 +1344,10 @@ async def start_tool_instance(
|
||||
ssh_target,
|
||||
)
|
||||
|
||||
# Ensure staged bind-mount sources are owned by the container user so
|
||||
# directories like ~/.config remain writable inside the container.
|
||||
_chown_staged_mounts(extra_volumes, instance_dir, container_uid, container_gid)
|
||||
|
||||
# ── MANIFEST-BASED FLOW ──────────────────────────────────────
|
||||
resolved_manifest = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user