Skip to content

Commit e3bfca3

Browse files
authored
Merge pull request #5004 from cyphar/1.4-pids-limit-0
[1.4] runtime-spec: update pids.limit handling to match new guidance
2 parents c5528ab + 41e6b4f commit e3bfca3

File tree

20 files changed

+316
-62
lines changed

20 files changed

+316
-62
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased 1.4.z]
88

9+
### Breaking ###
10+
- The handling of `pids.limit` has been updated to match the newer guidance
11+
from the OCI runtime specification. In particular, now a maximum limit value
12+
of `0` will be treated as an actual limit (due to limitations with systemd,
13+
it will be treated the same as a limit value of `1`). We only expect users
14+
that explicitly set `pids.limit` to `0` will see a behaviour change.
15+
(opencontainers/cgroups#48, #4949)
16+
17+
### Fixed ###
18+
- cgroups: provide iocost statistics for cgroupv2. (opencontainers/cgroups#43)
19+
- cgroups: retry DBus connection when it fails with EAGAIN.
20+
(opencontainers/cgroups#45)
21+
- cgroups: improve `cpuacct.usage_all` resilience when parsing data from
22+
patched kernels (such as the Tencent kernels). (opencontainers/cgroups#46,
23+
opencontainers/cgroups#50)
24+
925
## [1.4.0-rc.3] - 2025-11-05
1026

1127
> その日、人類は思い出した。

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ require (
1414
github.com/moby/sys/user v0.4.0
1515
github.com/moby/sys/userns v0.1.0
1616
github.com/mrunalp/fileutils v0.5.1
17-
github.com/opencontainers/cgroups v0.0.5
18-
github.com/opencontainers/runtime-spec v1.2.2-0.20250818071321-383cadbf08c0
17+
github.com/opencontainers/cgroups v0.0.6
18+
github.com/opencontainers/runtime-spec v1.3.0
1919
github.com/opencontainers/selinux v1.13.0
2020
github.com/seccomp/libseccomp-golang v0.11.1
2121
github.com/sirupsen/logrus v1.9.3

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g
4646
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
4747
github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q=
4848
github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
49-
github.com/opencontainers/cgroups v0.0.5 h1:DRITAqcOnY0uSBzIpt1RYWLjh5DPDiqUs4fY6Y0ktls=
50-
github.com/opencontainers/cgroups v0.0.5/go.mod h1:oWVzJsKK0gG9SCRBfTpnn16WcGEqDI8PAcpMGbqWxcs=
51-
github.com/opencontainers/runtime-spec v1.2.2-0.20250818071321-383cadbf08c0 h1:RLn0YfUWkiqPGtgUANvJrcjIkCHGRl3jcz/c557M28M=
52-
github.com/opencontainers/runtime-spec v1.2.2-0.20250818071321-383cadbf08c0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
49+
github.com/opencontainers/cgroups v0.0.6 h1:tfZFWTIIGaUUFImTyuTg+Mr5x8XRiSdZESgEBW7UxuI=
50+
github.com/opencontainers/cgroups v0.0.6/go.mod h1:oWVzJsKK0gG9SCRBfTpnn16WcGEqDI8PAcpMGbqWxcs=
51+
github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg=
52+
github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
5353
github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
5454
github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
5555
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

libcontainer/integration/exec_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,20 +526,22 @@ func TestPidsSystemd(t *testing.T) {
526526
testPids(t, true)
527527
}
528528

529+
func mkPtr[T any](v T) *T { return &v }
530+
529531
func testPids(t *testing.T, systemd bool) {
530532
if testing.Short() {
531533
return
532534
}
533535

534536
config := newTemplateConfig(t, &tParam{systemd: systemd})
535-
config.Cgroups.Resources.PidsLimit = -1
537+
config.Cgroups.Resources.PidsLimit = mkPtr[int64](-1)
536538

537539
// Running multiple processes, expecting it to succeed with no pids limit.
538540
runContainerOk(t, config, "/bin/sh", "-c", "/bin/true | /bin/true | /bin/true | /bin/true")
539541

540542
// Enforce a permissive limit. This needs to be fairly hand-wavey due to the
541543
// issues with running Go binaries with pids restrictions (see below).
542-
config.Cgroups.Resources.PidsLimit = 64
544+
config.Cgroups.Resources.PidsLimit = mkPtr[int64](64)
543545
runContainerOk(t, config, "/bin/sh", "-c", `
544546
/bin/true | /bin/true | /bin/true | /bin/true | /bin/true | /bin/true | bin/true | /bin/true |
545547
/bin/true | /bin/true | /bin/true | /bin/true | /bin/true | /bin/true | bin/true | /bin/true |
@@ -548,7 +550,7 @@ func testPids(t *testing.T, systemd bool) {
548550

549551
// Enforce a restrictive limit. 64 * /bin/true + 1 * shell should cause
550552
// this to fail reliably.
551-
config.Cgroups.Resources.PidsLimit = 64
553+
config.Cgroups.Resources.PidsLimit = mkPtr[int64](64)
552554
out, _, err := runContainer(t, config, "/bin/sh", "-c", `
553555
/bin/true | /bin/true | /bin/true | /bin/true | /bin/true | /bin/true | bin/true | /bin/true |
554556
/bin/true | /bin/true | /bin/true | /bin/true | /bin/true | /bin/true | bin/true | /bin/true |

man/runc-update.8.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ stdin. If this option is used, all other options are ignored.
8585
(i.e. use unlimited swap).
8686

8787
**--pids-limit** _num_
88-
: Set the maximum number of processes allowed in the container.
88+
: Set the maximum number of processes allowed in the container. Use **-1** to
89+
unset the limit.
8990

9091
**--l3-cache-schema** _value_
9192
: Set the value for Intel RDT/CAT L3 cache schema.

tests/integration/cgroups.bats

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,37 @@ convert_hugetlb_size() {
320320
done
321321
}
322322

323+
# https://github.com/opencontainers/runc/issues/4014.
324+
@test "runc run (pids.limit=0 means 1)" {
325+
[ $EUID -ne 0 ] && requires rootless_cgroup
326+
requires cgroups_pids
327+
328+
set_cgroups_path
329+
update_config '.linux.resources.pids.limit = 0'
330+
331+
runc run -d --console-socket "$CONSOLE_SOCKET" test_pids
332+
[ "$status" -eq 0 ]
333+
# systemd doesn't support TasksMax=0 so runc will silently remap it to 1
334+
# (for consistency, we do this for systemd *and* cgroupfs).
335+
check_cgroup_value "pids.max" "1"
336+
check_systemd_value "TasksMax" "1"
337+
}
338+
339+
# https://github.com/opencontainers/runc/issues/4014.
340+
@test "runc run (pids.limit=-1 means unlimited)" {
341+
[ $EUID -ne 0 ] && requires rootless_cgroup
342+
requires cgroups_pids
343+
344+
set_cgroups_path
345+
update_config '.linux.resources.pids.limit = -1'
346+
347+
runc run -d --console-socket "$CONSOLE_SOCKET" test_pids
348+
[ "$status" -eq 0 ]
349+
check_cgroup_value "pids.max" "max"
350+
# systemd < v227 shows UINT64_MAX instead of "infinity".
351+
check_systemd_value "TasksMax" "infinity" "18446744073709551615"
352+
}
353+
323354
@test "runc run (cgroup v2 resources.unified only)" {
324355
requires root cgroups_v2
325356

tests/integration/update.bats

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,37 @@ EOF
330330
check_cpu_shares 100
331331
}
332332

333+
@test "update pids.limit" {
334+
[ $EUID -ne 0 ] && requires rootless_cgroup
335+
requires cgroups_pids
336+
337+
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
338+
[ "$status" -eq 0 ]
339+
340+
check_cgroup_value "pids.max" 20
341+
check_systemd_value "TasksMax" 20
342+
343+
runc update test_update --pids-limit 12345
344+
[ "$status" -eq 0 ]
345+
346+
check_cgroup_value "pids.max" "12345"
347+
check_systemd_value "TasksMax" "12345"
348+
349+
runc update test_update --pids-limit -1
350+
[ "$status" -eq 0 ]
351+
352+
check_cgroup_value "pids.max" "max"
353+
# systemd < v227 shows UINT64_MAX instead of "infinity".
354+
check_systemd_value "TasksMax" "infinity" "18446744073709551615"
355+
356+
runc update test_update --pids-limit 0
357+
[ "$status" -eq 0 ]
358+
359+
# systemd doesn't support TasksMax=0 so runc will silently remap it to 1.
360+
check_cgroup_value "pids.max" "1"
361+
check_systemd_value "TasksMax" "1"
362+
}
363+
333364
@test "cpu burst" {
334365
[ $EUID -ne 0 ] && requires rootless_cgroup
335366
requires cgroups_cpu_burst

update.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ import (
1717
"github.com/urfave/cli"
1818
)
1919

20-
func i64Ptr(i int64) *int64 { return &i }
21-
func u64Ptr(i uint64) *uint64 { return &i }
22-
func u16Ptr(i uint16) *uint16 { return &i }
23-
func boolPtr(b bool) *bool { return &b }
20+
func mkPtr[T any](v T) *T { return &v }
2421

2522
var updateCommand = cli.Command{
2623
Name: "update",
@@ -147,9 +144,9 @@ other options are ignored.
147144
}
148145

149146
r := specs.LinuxResources{
150-
// nil and u64Ptr(0) are not interchangeable
147+
// nil and mkPtr(0) are not interchangeable
151148
Memory: &specs.LinuxMemory{
152-
CheckBeforeUpdate: boolPtr(false), // constant
149+
CheckBeforeUpdate: mkPtr(false), // constant
153150
},
154151
CPU: &specs.LinuxCPU{},
155152
BlockIO: &specs.LinuxBlockIO{},
@@ -179,7 +176,7 @@ other options are ignored.
179176
}
180177
} else {
181178
if val := context.Int("blkio-weight"); val != 0 {
182-
r.BlockIO.Weight = u16Ptr(uint16(val))
179+
r.BlockIO.Weight = mkPtr(uint16(val))
183180
}
184181
if val := context.String("cpuset-cpus"); val != "" {
185182
r.CPU.Cpus = val
@@ -192,7 +189,7 @@ other options are ignored.
192189
if err != nil {
193190
return fmt.Errorf("invalid value for cpu-idle: %w", err)
194191
}
195-
r.CPU.Idle = i64Ptr(idle)
192+
r.CPU.Idle = mkPtr(idle)
196193
}
197194

198195
for _, pair := range []struct {
@@ -252,17 +249,19 @@ other options are ignored.
252249
}
253250
}
254251

255-
r.Pids.Limit = int64(context.Int("pids-limit"))
252+
if context.IsSet("pids-limit") {
253+
r.Pids.Limit = mkPtr(int64(context.Int("pids-limit")))
254+
}
256255
}
257256

258257
// Fix up values
259258
if r.Memory.Limit != nil && *r.Memory.Limit == -1 && r.Memory.Swap == nil {
260259
// To avoid error "unable to set swap limit without memory limit"
261-
r.Memory.Swap = i64Ptr(0)
260+
r.Memory.Swap = mkPtr[int64](0)
262261
}
263262
if r.CPU.Idle != nil && r.CPU.Shares == nil {
264263
// To avoid error "failed to write \"4\": write /sys/fs/cgroup/runc-cgroups-integration-test/test-cgroup-7341/cpu.weight: invalid argument"
265-
r.CPU.Shares = u64Ptr(0)
264+
r.CPU.Shares = mkPtr[uint64](0)
266265
}
267266

268267
if (r.Memory.Kernel != nil) || (r.Memory.KernelTCP != nil) { //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.

vendor/github.com/opencontainers/cgroups/config_linux.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/opencontainers/cgroups/fs/cpuacct.go

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)