fix isolation startup cleanup and optional Linux mounts

This commit is contained in:
lxowalle 2026-04-08 17:03:01 +08:00
parent a009e76da2
commit d38ca161ec
2 changed files with 48 additions and 11 deletions

View file

@ -218,7 +218,7 @@ func DefaultExposePaths(root string) []config.ExposePath {
}
func defaultLinuxSystemExposePaths() []config.ExposePath {
return []config.ExposePath{
return existingExposePaths([]config.ExposePath{
{Source: "/usr", Target: "/usr", Mode: "ro"},
{Source: "/bin", Target: "/bin", Mode: "ro"},
{Source: "/lib", Target: "/lib", Mode: "ro"},
@ -236,7 +236,19 @@ func defaultLinuxSystemExposePaths() []config.ExposePath {
{Source: "/etc/alternatives", Target: "/etc/alternatives", Mode: "ro"},
{Source: "/usr/share/zoneinfo", Target: "/usr/share/zoneinfo", Mode: "ro"},
{Source: "/etc/localtime", Target: "/etc/localtime", Mode: "ro"},
})
}
// existingExposePaths keeps only the builtin host paths that exist on the
// current machine so Linux isolation does not fail on distro-specific paths.
func existingExposePaths(items []config.ExposePath) []config.ExposePath {
filtered := make([]config.ExposePath, 0, len(items))
for _, item := range items {
if _, err := os.Stat(item.Source); err == nil {
filtered = append(filtered, item)
}
}
return filtered
}
// MergeExposePaths merges built-in rules with user overrides. Rules are keyed
@ -363,12 +375,12 @@ func Start(cmd *exec.Cmd) error {
var err error
root, err = ResolveInstanceRoot()
if err != nil {
_ = cmd.Process.Kill()
terminateStartedCommand(cmd)
return err
}
}
if err := postStartPlatformIsolation(cmd, isolation, root); err != nil {
_ = cmd.Process.Kill()
terminateStartedCommand(cmd)
return err
}
return nil
@ -390,17 +402,26 @@ func Run(cmd *exec.Cmd) error {
var err error
root, err = ResolveInstanceRoot()
if err != nil {
_ = cmd.Process.Kill()
terminateStartedCommand(cmd)
return err
}
}
if err := postStartPlatformIsolation(cmd, isolation, root); err != nil {
_ = cmd.Process.Kill()
terminateStartedCommand(cmd)
return err
}
return cmd.Wait()
}
func terminateStartedCommand(cmd *exec.Cmd) {
cleanupPendingPlatformResources(cmd)
if cmd == nil || cmd.Process == nil {
return
}
_ = cmd.Process.Kill()
_ = cmd.Wait()
}
// PrepareCommand mutates the command in-place so it inherits the configured
// isolated environment before being started by the caller.
func PrepareCommand(cmd *exec.Cmd) error {

View file

@ -176,12 +176,11 @@ func TestValidateWindowsExposePaths(t *testing.T) {
func TestDefaultLinuxSystemExposePaths(t *testing.T) {
paths := defaultLinuxSystemExposePaths()
needed := map[string]bool{
"/etc/hosts": false,
"/etc/nsswitch.conf": false,
"/etc/ssl": false,
"/usr/share/zoneinfo": false,
"/etc/localtime": false,
needed := map[string]bool{}
for _, path := range []string{"/etc/hosts", "/etc/nsswitch.conf", "/etc/ssl", "/usr/share/zoneinfo", "/etc/localtime"} {
if _, err := os.Stat(path); err == nil {
needed[path] = false
}
}
for _, item := range paths {
if _, ok := needed[item.Source]; ok {
@ -195,6 +194,23 @@ func TestDefaultLinuxSystemExposePaths(t *testing.T) {
}
}
func TestExistingExposePaths_SkipsMissingPaths(t *testing.T) {
existing := filepath.Join(t.TempDir(), "existing")
if err := os.MkdirAll(existing, 0o755); err != nil {
t.Fatalf("os.MkdirAll() error = %v", err)
}
filtered := existingExposePaths([]config.ExposePath{
{Source: existing, Target: existing, Mode: "ro"},
{Source: filepath.Join(t.TempDir(), "missing"), Target: "/missing", Mode: "ro"},
})
if len(filtered) != 1 {
t.Fatalf("existingExposePaths() len = %d, want 1", len(filtered))
}
if got := filtered[0]; got.Source != existing {
t.Fatalf("existingExposePaths()[0] = %+v, want source=%q", got, existing)
}
}
func TestPrepareCommand_AppliesUserEnv(t *testing.T) {
t.Setenv(config.EnvHome, filepath.Join(t.TempDir(), "home"))
if runtime.GOOS == "linux" {