Map pids-limit 0 to unlimited for runc

Docker documents HostConfig.PidsLimit 0 as unlimited, but runc sets
pids.max=1 for OCI pids.limit 0. Normalize 0 to -1 when building the
OCI spec so native CLI, compat API, and kube play behave consistently.

Fixes: https://github.com/podman-container-tools/podman/issues/29826

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
This commit is contained in:
Jan Rodák 2026-09-23 18:40:13 +02:00
parent 77d1fdf87a
commit 5fa0cb1090
No known key found for this signature in database
GPG key ID: D458A9B20435C2BF
6 changed files with 41 additions and 3 deletions

View file

@ -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

View file

@ -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,
}
}

14
pkg/specgenutil/pids.go Normal file
View file

@ -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
}

View file

@ -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))
}

View file

@ -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

View file

@ -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")