Support passing of Ulimits as -1 to mean max

Docker allows the passing of -1 to indicate the maximum limit
allowed for the current process.

Fixes: https://github.com/containers/podman/issues/19319

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2023-09-08 07:03:49 -04:00
parent 55b9ea3ec7
commit 18d6bb40d5
8 changed files with 65 additions and 3 deletions

View File

@ -11,6 +11,9 @@ Ulimit options. Sets the ulimits values inside of the container.
$ podman run --ulimit nofile=1024:1024 --rm ubi9 ulimit -n
1024
Set -1 for the soft or hard limit to set the limit to the maximum limit of the current
process. In rootful mode this is often unlimited.
Use **host** to copy the current configuration from the host.
Don't use nproc with the ulimit flag as Linux uses nproc to set the

View File

@ -644,7 +644,8 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
for _, rlimit := range c.config.Spec.Process.Rlimits {
if rlimit.Type == "RLIMIT_NOFILE" {
nofileSet = true
} else if rlimit.Type == "RLIMIT_NPROC" {
}
if rlimit.Type == "RLIMIT_NPROC" {
nprocSet = true
}
}

View File

@ -324,6 +324,5 @@ func GetLimits(resource *spec.LinuxResources) (runcconfig.Resources, error) {
// Unified state
final.Unified = resource.Unified
return *final, nil
}

View File

@ -18,6 +18,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) {
for _, u := range s.Rlimits {
name := "RLIMIT_" + strings.ToUpper(u.Type)
u = subNegativeOne(u)
g.AddProcessRlimits(name, u.Hard, u.Soft)
}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/opencontainers/runtime-spec/specs-go"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
)
@ -172,3 +173,7 @@ func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWei
devs := []spec.LinuxWeightDevice{}
return devs, nil
}
func subNegativeOne(u specs.POSIXRlimit) specs.POSIXRlimit {
return u
}

View File

@ -17,8 +17,10 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/docker/go-units"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@ -357,3 +359,37 @@ func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWei
}
return devs, nil
}
// subNegativeOne translates Hard or soft limits of -1 to the current
// processes Max limit
func subNegativeOne(u spec.POSIXRlimit) spec.POSIXRlimit {
if !rootless.IsRootless() ||
(int64(u.Hard) != -1 && int64(u.Soft) != -1) {
return u
}
ul, err := units.ParseUlimit(fmt.Sprintf("%s=%d:%d", u.Type, int64(u.Soft), int64(u.Hard)))
if err != nil {
logrus.Warnf("Failed to check %s ulimit %q", u.Type, err)
return u
}
rl, err := ul.GetRlimit()
if err != nil {
logrus.Warnf("Failed to check %s ulimit %q", u.Type, err)
return u
}
var rlimit unix.Rlimit
if err := unix.Getrlimit(rl.Type, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
return u
}
if int64(u.Hard) == -1 {
u.Hard = rlimit.Max
}
if int64(u.Soft) == -1 {
u.Soft = rlimit.Max
}
return u
}

View File

@ -465,7 +465,7 @@ var _ = Describe("Podman inspect", func() {
Expect(inspect[0].NetworkSettings.Networks).To(HaveLen(1))
})
It("Container inspect with unlimited uilimits should be -1", func() {
It("Container inspect with unlimited ulimits should be -1", func() {
ctrName := "testctr"
session := podmanTest.Podman([]string{"run", "-d", "--ulimit", "core=-1:-1", "--name", ctrName, ALPINE, "top"})
session.WaitWithDefaultTimeout()

View File

@ -1149,6 +1149,23 @@ EOF
assert "$output" =~ " ${nofile2} * ${nofile2} * files"
}
@test "podman run ulimit with -1" {
max=unlimited
if is_rootless; then
run ulimit -c -H
max=$output
fi
run_podman run --ulimit core=-1:-1 --rm $IMAGE grep core /proc/self/limits
assert "$output" =~ " ${max} * ${max} * bytes"
run_podman run --ulimit core=1000:-1 --rm $IMAGE grep core /proc/self/limits
assert "$output" =~ " 1000 * ${max} * bytes"
run_podman 125 run --ulimit core=-1:1000 --rm $IMAGE grep core /proc/self/limits
is "$output" "Error: ulimit option \"core=-1:1000\" requires name=SOFT:HARD, failed to be parsed: ulimit soft limit must be less than or equal to hard limit: soft: -1 (unlimited), hard: 1000"
}
@test "podman run bad --name" {
randomname=$(random_string 30)
run_podman 125 create --name "$randomname/bad" $IMAGE