Skip to content

Commit

Permalink
runc run: treat pids.limit=0 as unlimited
Browse files Browse the repository at this point in the history
It has been pointed out that runc incorrectly ignores pids.limit=0 set
in the runtime spec. This happens because runtime-spec says "default is
unlimited" and also allows for Pids to not be set at all, thus
distinguishing unset (Resources.Pids == nil) from unlimited
(Resources.Pids.Limit <= 0).

Internally, runc also distinguishes unset from unlimited, but since we
do not use a pointer, we treat 0 as unset and -1 as unlimited.

Add a conversion code to libcontainer/specconv.

Add a test case to check that starting a container with pids.limit=0
results in no pids limit (the test fails before the fix when systemd
cgroup manager is used, as systemd apparently uses parent's TasksMax).

NOTE that runc update still treats 0 as "unset".

Finally, fix/update the documentation here and there.

Should fix issue 4014.

Reported-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin authored and lifubang committed Oct 20, 2023
1 parent 36e3e42 commit 4c61f68
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion libcontainer/configs/cgroup_linux.go
Expand Up @@ -90,7 +90,7 @@ type Resources struct {
// cgroup SCHED_IDLE
CPUIdle *int64 `json:"cpu_idle,omitempty"`

// Process limit; set <= `0' to disable limit.
// Maximum number of tasks; 0 for unset, -1 for max/unlimited.
PidsLimit int64 `json:"pids_limit"`

// Specifies per cgroup weight, range is from 10 to 1000.
Expand Down
8 changes: 7 additions & 1 deletion libcontainer/specconv/spec_linux.go
Expand Up @@ -775,8 +775,14 @@ func CreateCgroupConfig(opts *CreateOpts, defaultDevs []*devices.Device) (*confi
c.Resources.CpusetMems = r.CPU.Mems
c.Resources.CPUIdle = r.CPU.Idle
}
// Convert pids limit from the runtime-spec value (where any value <= 0 means "unlimited")
// to internal runc value (where -1 is "unlimited", and 0 is "unset").
if r.Pids != nil {
c.Resources.PidsLimit = r.Pids.Limit
if r.Pids.Limit > 0 {
c.Resources.PidsLimit = r.Pids.Limit
} else {
c.Resources.PidsLimit = -1
}
}
if r.BlockIO != nil {
if r.BlockIO.Weight != nil {
Expand Down
2 changes: 1 addition & 1 deletion man/runc-update.8.md
Expand Up @@ -85,7 +85,7 @@ stdin. If this option is used, all other options are ignored.
(i.e. use unlimited swap).

**--pids-limit** _num_
: Set the maximum number of processes allowed in the container.
: Set the maximum number of tasks. Use **-1** for unlimited.

**--l3-cache-schema** _value_
: Set the value for Intel RDT/CAT L3 cache schema.
Expand Down
14 changes: 14 additions & 0 deletions tests/integration/cgroups.bats
Expand Up @@ -263,6 +263,20 @@ convert_hugetlb_size() {
done
}

# https://github.com/opencontainers/runc/issues/4014.
@test "runc run (pids.limit=0 means unlimited)" {
[ $EUID -ne 0 ] && requires rootless_cgroup

set_cgroups_path
update_config '.linux.resources.pids.limit |= 0'

runc run -d --console-socket "$CONSOLE_SOCKET" test_pids
[ "$status" -eq 0 ]
check_cgroup_value "pids.max" "max"
# systemd < v227 shows UINT64_MAX instead of "infinity".
check_systemd_value "TasksMax" "infinity" "18446744073709551615"
}

@test "runc run (cgroup v2 resources.unified only)" {
requires root cgroups_v2

Expand Down
4 changes: 2 additions & 2 deletions update.go
Expand Up @@ -122,11 +122,11 @@ other options are ignored.
},
cli.StringFlag{
Name: "memory-swap",
Usage: "Total memory usage (memory + swap); set '-1' to enable unlimited swap",
Usage: "Total memory usage (memory + swap); use '-1' to enable unlimited swap",
},
cli.IntFlag{
Name: "pids-limit",
Usage: "Maximum number of pids allowed in the container",
Usage: "Maximum number of tasks; use '-1' for unlimited",
},
cli.StringFlag{
Name: "l3-cache-schema",
Expand Down

0 comments on commit 4c61f68

Please sign in to comment.