diff --git a/pkg/containermanager/providers/podman.go b/pkg/containermanager/providers/podman.go index 78aae997..bf098f4d 100644 --- a/pkg/containermanager/providers/podman.go +++ b/pkg/containermanager/providers/podman.go @@ -408,9 +408,11 @@ func (p *Podman) makeCreateCommand( options = append(options, "--systemd=always") } - // Use keep-id only if going rootless. + // Use keep-id only if going rootless. DBX_USERNS_NOLIMIT (set to a non-zero + // value) drops the :size cap, matching the shell (distrobox-create:962-977). if !p.root { - if dryRun || p.supportsKeepIDSize(ctx, containerImage) { + usernsNoLimit := usernsNoLimitEnabled() + if !usernsNoLimit && (dryRun || p.supportsKeepIDSize(ctx, containerImage)) { options = append(options, "--userns", "keep-id:size=65536") } else { options = append(options, "--userns", "keep-id") @@ -680,6 +682,14 @@ func commandExists(cmd string) bool { return err == nil } +// usernsNoLimitEnabled reports whether DBX_USERNS_NOLIMIT requests dropping the +// keep-id:size cap (any non-empty, non-"0" value), mirroring the shell's +// userns_nolimit (distrobox-create:159,962-977). +func usernsNoLimitEnabled() bool { + v := os.Getenv("DBX_USERNS_NOLIMIT") + return v != "" && v != "0" && v != "false" +} + // supportsKeepIDSize tests whether podman supports the keep-id:size= userns option // by attempting a quick container run. Older podman versions do not support the size suboption. func (p *Podman) supportsKeepIDSize(ctx context.Context, image string) bool { diff --git a/pkg/containermanager/providers/podman_internal_test.go b/pkg/containermanager/providers/podman_internal_test.go index be7f6d1f..1a28aa21 100644 --- a/pkg/containermanager/providers/podman_internal_test.go +++ b/pkg/containermanager/providers/podman_internal_test.go @@ -16,6 +16,40 @@ import ( "github.com/89luca89/distrobox/pkg/ui" ) +// DBX_USERNS_NOLIMIT (non-zero) drops the keep-id:size cap. +func TestUsernsNoLimitEnabled(t *testing.T) { + cases := map[string]bool{"": false, "0": false, "false": false, "1": true, "true": true, "yes": true} + for v, want := range cases { + t.Setenv("DBX_USERNS_NOLIMIT", v) + if got := usernsNoLimitEnabled(); got != want { + t.Errorf("DBX_USERNS_NOLIMIT=%q: got %v, want %v", v, got, want) + } + } +} + +// with DBX_USERNS_NOLIMIT set, rootless create uses plain keep-id (no :size). +func TestPodman_makeCreateCommandUsernsNoLimit(t *testing.T) { + t.Setenv("DBX_USERNS_NOLIMIT", "1") + podman := NewPodman(false, "sudo", false) + userEnv := &userenv.UserEnvironment{User: "user", UserID: "1000", GroupID: "1000", Home: "/home/user", Shell: "/bin/sh"} + + cmd := podman.makeCreateCommand( + t.Context(), + "my-container", "my-image", + []string{}, "my-hostname", []string{}, []string{}, + "", "", + false, false, "", "", + false, false, false, false, false, false, + false, // dryRun + userEnv, + "/path/to/distrobox-init", "/path/to/distrobox-export", "/path/to/distrobox-hostexec", + ) + cmdStr := strings.Join(cmd, " ") + + assert.Contains(t, cmdStr, "--userns keep-id") + assert.NotContains(t, cmdStr, "keep-id:size") +} + func TestPodman_makeCreateCommand(t *testing.T) { podman := NewPodman(false, "sudo", false)