Skip to content

Make rootfs hook chown best-effort for macOS support#7

Merged
JAORMX merged 1 commit into
mainfrom
fix/best-effort-chown-macos
Mar 3, 2026
Merged

Make rootfs hook chown best-effort for macOS support#7
JAORMX merged 1 commit into
mainfrom
fix/best-effort-chown-macos

Conversation

@JAORMX
Copy link
Copy Markdown
Contributor

@JAORMX JAORMX commented Mar 3, 2026

Summary

  • InjectAuthorizedKeys now uses an injected ChownFunc (defaulting to BestEffortLchown) instead of hard os.Chown, so it no longer fails with EPERM on macOS for non-root users
  • BestEffortLchown uses os.Lchown (symlink-safe) and swallows permission errors — the guest init handles authoritative ownership
  • New fixHomeOwnership step in boot.Run recursively chowns /home/sandbox and enforces SSH strict permissions (0700 for .ssh/, 0600 for files) as PID 1 before cap drop
  • Symlinks are skipped in the walk for defense-in-depth

Test plan

  • task fmt && task lint && task test passes
  • Hooks tests use recordingChown DI mock — run on any platform regardless of UID
  • fixhome_test.go covers permission enforcement, nested SSH files, missing home dir, symlink path detection
  • Manual: run brood-box on macOS as non-root — VM boots, SSH connects, files in /home/sandbox owned by sandbox user

🤖 Generated with Claude Code

On macOS, non-root users cannot os.Chown to a different UID, causing
InjectAuthorizedKeys to fail with EPERM. This makes VM startup
impossible on macOS without root.

Two-layer fix:
- Host side: InjectAuthorizedKeys now uses an injected ChownFunc
  (defaulting to BestEffortLchown) that swallows EPERM. Uses Lchown
  instead of Chown to avoid following symlinks in the rootfs.
- Guest side: New fixHomeOwnership step in boot.Run recursively
  chowns /home/sandbox and enforces SSH strict permissions (0700 for
  .ssh/, 0600 for files). Runs as PID 1 before cap drop, so chown
  always succeeds. Symlinks are skipped for safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JAORMX JAORMX requested a review from jhrozek March 3, 2026 11:18
JAORMX added a commit to stacklok/brood-box that referenced this pull request Mar 3, 2026
Replace os.Chown with bestEffortLchown in InjectGitConfig and
InjectMCPConfig hooks. On macOS, non-root users cannot chown files
to a different UID, causing VM startup to fail with EPERM.

bestEffortLchown uses os.Lchown (symlink-safe) and swallows
permission errors. The guest init in propolis now handles
authoritative ownership fixup at boot time as PID 1.

Depends on stacklok/go-microvm#7.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JAORMX JAORMX merged commit 8559435 into main Mar 3, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant