Skip to content

Commit ba5876c

Browse files
authored
Merge pull request #7 from stacklok/fix/best-effort-chown-macos
Make rootfs hook chown best-effort for macOS support
2 parents 4503004 + 5a29421 commit ba5876c

4 files changed

Lines changed: 20 additions & 6 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
1414
github.com/sergi/go-diff v1.4.0
1515
github.com/spf13/cobra v1.10.2
16-
github.com/stacklok/propolis v0.0.6
16+
github.com/stacklok/propolis v0.0.7-0.20260303111539-b54bd3284abf
1717
github.com/stacklok/toolhive v0.10.0
1818
github.com/stacklok/toolhive-core v0.0.6
1919
github.com/stretchr/testify v1.11.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,8 +628,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
628628
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
629629
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
630630
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
631-
github.com/stacklok/propolis v0.0.6 h1:Szfo4xeYX3pQpHzDOzSomo2zngIyFE3t4yRA4MqVPp0=
632-
github.com/stacklok/propolis v0.0.6/go.mod h1:GK7TUXCm4J8Hh/QFoIGuXE4szSt8PWDZWzj1JPpqxVU=
631+
github.com/stacklok/propolis v0.0.7-0.20260303111539-b54bd3284abf h1:HsQYq1H56kvEbgc+/4qwFpEr3HcyfMQ0b8dCcCHwesU=
632+
github.com/stacklok/propolis v0.0.7-0.20260303111539-b54bd3284abf/go.mod h1:GK7TUXCm4J8Hh/QFoIGuXE4szSt8PWDZWzj1JPpqxVU=
633633
github.com/stacklok/toolhive v0.10.0 h1:yXTR2ZbD83tGjSjSS2ypg61dYWZ3AwKxCyq3cACELOc=
634634
github.com/stacklok/toolhive v0.10.0/go.mod h1:5suFGdrDM9j8Vh/ULROVO2qImpm+kMklXHcVBNFxL9Y=
635635
github.com/stacklok/toolhive-core v0.0.6 h1:JLJpL4qyGh3z/fZKk+NNavziNCdtJlHoqroqBdWH6x8=

internal/infra/vm/mcpconfig.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,30 @@ import (
77
"encoding/json"
88
"errors"
99
"fmt"
10+
"log/slog"
1011
"os"
1112
"path/filepath"
1213

1314
toml "github.com/pelletier/go-toml/v2"
1415
)
1516

1617
// ChownFunc abstracts file ownership changes for testability.
17-
// Production code passes os.Chown; tests can pass a recording mock.
18+
// Production code uses bestEffortLchown; tests can pass a recording mock.
1819
type ChownFunc func(path string, uid, gid int) error
1920

21+
// bestEffortLchown attempts os.Lchown and silently ignores permission errors.
22+
// On macOS non-root users cannot chown to a different UID; the guest init
23+
// will fix ownership at boot time. Lchown is used instead of Chown to avoid
24+
// following symlinks in the rootfs.
25+
func bestEffortLchown(path string, uid, gid int) error {
26+
if err := os.Lchown(path, uid, gid); err != nil {
27+
if !os.IsPermission(err) {
28+
slog.Warn("lchown failed", "path", path, "uid", uid, "gid", gid, "err", err)
29+
}
30+
}
31+
return nil
32+
}
33+
2034
// sandboxHome is the home directory of the sandbox user inside the guest.
2135
// Config files are written here because /workspace is mounted via virtiofs
2236
// and would shadow anything written into the rootfs at that path.

internal/infra/vm/runner.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func (r *PropolisRunner) Start(ctx context.Context, cfg domvm.VMConfig) (domvm.V
149149
hooks.InjectFile("/etc/ssh/ssh_host_ecdsa_key", hostKeyPEM, 0o600),
150150
InjectInitBinary(),
151151
hooks.InjectEnvFile("/etc/sandbox-env", cfg.EnvVars),
152-
InjectGitConfig(cfg.GitIdentity, cfg.HasGitToken, os.Chown),
152+
InjectGitConfig(cfg.GitIdentity, cfg.HasGitToken, bestEffortLchown),
153153
),
154154
propolis.WithInitOverride("/bbox-init"),
155155
propolis.WithPostBoot(func(ctx context.Context, _ *propolis.VM) error {
@@ -198,7 +198,7 @@ func (r *PropolisRunner) Start(ctx context.Context, cfg domvm.VMConfig) (domvm.V
198198
// Add MCP config injection hook if host services and agent format are set.
199199
if len(cfg.HostServices) > 0 && cfg.MCPConfigFormat != "" && cfg.MCPConfigFormat != agent.MCPConfigFormatNone {
200200
opts = append(opts, propolis.WithRootFSHook(
201-
InjectMCPConfig(cfg.MCPConfigFormat, topology.GatewayIP, cfg.HostServices[0].Port, os.Chown),
201+
InjectMCPConfig(cfg.MCPConfigFormat, topology.GatewayIP, cfg.HostServices[0].Port, bestEffortLchown),
202202
))
203203
}
204204

0 commit comments

Comments
 (0)