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
No known key found for this signature in database
GPG Key ID: A2DF901DABE2C028
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 $ podman run --ulimit nofile=1024:1024 --rm ubi9 ulimit -n
1024 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. 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 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 { for _, rlimit := range c.config.Spec.Process.Rlimits {
if rlimit.Type == "RLIMIT_NOFILE" { if rlimit.Type == "RLIMIT_NOFILE" {
nofileSet = true nofileSet = true
} else if rlimit.Type == "RLIMIT_NPROC" { }
if rlimit.Type == "RLIMIT_NPROC" {
nprocSet = true nprocSet = true
} }
} }

View File

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

View File

@ -18,6 +18,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) {
for _, u := range s.Rlimits { for _, u := range s.Rlimits {
name := "RLIMIT_" + strings.ToUpper(u.Type) name := "RLIMIT_" + strings.ToUpper(u.Type)
u = subNegativeOne(u)
g.AddProcessRlimits(name, u.Hard, u.Soft) 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"
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgen"
"github.com/opencontainers/runtime-spec/specs-go"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/generate"
) )
@ -172,3 +173,7 @@ func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWei
devs := []spec.LinuxWeightDevice{} devs := []spec.LinuxWeightDevice{}
return devs, nil 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/libpod/define"
"github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgen"
"github.com/docker/go-units"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/generate"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -357,3 +359,37 @@ func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWei
} }
return devs, nil 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)) 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" ctrName := "testctr"
session := podmanTest.Podman([]string{"run", "-d", "--ulimit", "core=-1:-1", "--name", ctrName, ALPINE, "top"}) session := podmanTest.Podman([]string{"run", "-d", "--ulimit", "core=-1:-1", "--name", ctrName, ALPINE, "top"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()

View File

@ -1149,6 +1149,23 @@ EOF
assert "$output" =~ " ${nofile2} * ${nofile2} * files" 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" { @test "podman run bad --name" {
randomname=$(random_string 30) randomname=$(random_string 30)
run_podman 125 create --name "$randomname/bad" $IMAGE run_podman 125 create --name "$randomname/bad" $IMAGE