diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 3ba2c17096..d20505bd47 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -864,7 +864,8 @@ func UpdateContainer(w http.ResponseWriter, r *http.Request) { if resources.Pids == nil { resources.Pids = new(spec.LinuxPids) } - resources.Pids.Limit = options.PidsLimit + limit := specgenutil.PidsLimitForOCI(*options.PidsLimit) + resources.Pids.Limit = &limit } // Blkio Weight diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 2aced8ef48..6c0abaddd7 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -39,6 +39,7 @@ import ( "go.podman.io/podman/v6/pkg/k8s.io/apimachinery/pkg/util/intstr" "go.podman.io/podman/v6/pkg/specgen" "go.podman.io/podman/v6/pkg/specgen/generate" + "go.podman.io/podman/v6/pkg/specgenutil" systemdDefine "go.podman.io/podman/v6/pkg/systemd/define" "go.podman.io/podman/v6/pkg/util" "go.podman.io/storage/pkg/system" @@ -410,11 +411,12 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener if err != nil { return nil, err } + limit := specgenutil.PidsLimitForOCI(pidslimitAsInt) if s.ResourceLimits == nil { s.ResourceLimits = &spec.LinuxResources{} } s.ResourceLimits.Pids = &spec.LinuxPids{ - Limit: &pidslimitAsInt, + Limit: &limit, } } diff --git a/pkg/specgenutil/pids.go b/pkg/specgenutil/pids.go new file mode 100644 index 0000000000..6fcd151dae --- /dev/null +++ b/pkg/specgenutil/pids.go @@ -0,0 +1,14 @@ +package specgenutil + +// PidsLimitForOCI returns the value to store in the OCI runtime spec +// linux.resources.pids.limit field. +// +// Docker documents HostConfig.PidsLimit 0 as unlimited. runc maps OCI limit 0 to +// cgroup pids.max=1, while -1 means unlimited. crun treats 0 as unlimited. +// Normalize 0 to -1 so all runtimes get unlimited pids. +func PidsLimitForOCI(limit int64) int64 { + if limit == 0 { + return -1 + } + return limit +} diff --git a/pkg/specgenutil/pids_test.go b/pkg/specgenutil/pids_test.go new file mode 100644 index 0000000000..7970dd2a23 --- /dev/null +++ b/pkg/specgenutil/pids_test.go @@ -0,0 +1,13 @@ +package specgenutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPidsLimitForOCI(t *testing.T) { + assert.Equal(t, int64(-1), PidsLimitForOCI(0)) + assert.Equal(t, int64(-1), PidsLimitForOCI(-1)) + assert.Equal(t, int64(2048), PidsLimitForOCI(2048)) +} diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 03fafbf679..0a0fb8861d 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -1328,8 +1328,9 @@ func GetResources(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) } } if c.PIDsLimit != nil { + limit := PidsLimitForOCI(*c.PIDsLimit) pids := specs.LinuxPids{ - Limit: c.PIDsLimit, + Limit: &limit, } s.ResourceLimits.Pids = &pids diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 95d7d02e38..d893ee609c 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1918,6 +1918,13 @@ VOLUME %s`, ALPINE, volPath, volPath) Expect(session.OutputToString()).To(ContainSubstring(limit)) }) + It("podman run verify pids-limit 0 is unlimited", func() { + session := podmanTest.Podman([]string{"run", "--pids-limit", "0", "--net=none", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(ExitCleanly()) + Expect(session.OutputToString()).To(ContainSubstring("max")) + }) + It("podman run umask", func() { if !strings.Contains(podmanTest.OCIRuntime, "crun") { Skip("Test only works on crun")