From 5a7b910f93f2712618807c9eaf97392dcaa07592 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 1 Jul 2020 14:32:49 -0400 Subject: [PATCH] In rootless + cgroupsv1, resource limits are an error However, in some cases (unset limits), we can completely remove the limit and avoid errors. This works around a bug where the Podman frontend is setting a Pids limit of 0 on some rootless systems. For now, this is only implemented for the PID limit. It can easily be extended to other resource limits, but it is a fair bit of code to do so, so I leave that exercise to someone else. Fixes #6834 Signed-off-by: Matthew Heon --- pkg/domain/infra/abi/system.go | 27 --------------------------- pkg/specgen/generate/validate.go | 25 +++++++++++++++++++++---- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 0511289ab0..b347fbafa3 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -8,7 +8,6 @@ import ( "os/exec" "path/filepath" "strconv" - "syscall" "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" @@ -146,32 +145,6 @@ func movePauseProcessToScope() error { return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope") } -func setRLimits() error { // nolint:deadcode,unused - rlimits := new(syscall.Rlimit) - rlimits.Cur = 1048576 - rlimits.Max = 1048576 - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - return errors.Wrapf(err, "error getting rlimits") - } - rlimits.Cur = rlimits.Max - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - return errors.Wrapf(err, "error setting new rlimits") - } - } - return nil -} - -func setUMask() { // nolint:deadcode,unused - // Be sure we can create directories with 0755 mode. - syscall.Umask(0022) -} - -// checkInput can be used to verify any of the globalopt values -func checkInput() error { // nolint:deadcode,unused - return nil -} - // SystemPrune removes unused data from the system. Pruning pods, containers, volumes and images. func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) { var systemPruneReport = new(entities.SystemPruneReport) diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go index bb3ca99072..1a5e70ee0e 100644 --- a/pkg/specgen/generate/validate.go +++ b/pkg/specgen/generate/validate.go @@ -3,6 +3,7 @@ package generate import ( "github.com/containers/common/pkg/sysinfo" "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/specgen" "github.com/pkg/errors" ) @@ -23,6 +24,25 @@ func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) { return warnings, nil } + if rootless.IsRootless() { + // Interpreting 0 as unset - remove any unset limits + if s.ResourceLimits.Pids != nil && s.ResourceLimits.Pids.Limit == 0 { + s.ResourceLimits.Pids = nil + } + + // We are guaranteed to be cgroups v1 + rootless. Resource + // limits are not acceptable. But if everything is unset, we can + // just remove the block entirely. + if s.ResourceLimits.Memory == nil && s.ResourceLimits.Memory == nil && + s.ResourceLimits.CPU == nil && s.ResourceLimits.BlockIO == nil && + s.ResourceLimits.HugepageLimits == nil && s.ResourceLimits.Network == nil && + s.ResourceLimits.Rdma == nil && s.ResourceLimits.Pids == nil { + s.ResourceLimits = nil + return warnings, nil + } + return warnings, errors.New("resource limits cannot be set for rootless containers in cgroups v1 mode") + } + // Memory checks if s.ResourceLimits.Memory != nil { memory := s.ResourceLimits.Memory @@ -70,10 +90,7 @@ func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) { // Pids checks if s.ResourceLimits.Pids != nil { - pids := s.ResourceLimits.Pids - // TODO: Should this be 0, or checking that ResourceLimits.Pids - // is set at all? - if pids.Limit > 0 && !sysInfo.PidsLimit { + if !sysInfo.PidsLimit { warnings = append(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.") s.ResourceLimits.Pids = nil }