spec: clamp rlimits without CAP_SYS_RESOURCE

commit 5ebba75dbd implemented this
behaviour for rootless users and later commit
0a69aefa41 changed it when in a user
namespace, but the same limitation exists for root without
CAP_SYS_RESOURCE.  Change the check to use the clamp to the current
values if running without CAP_SYS_RESOURCE.

Closes: https://github.com/containers/podman/issues/24692

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2024-11-27 17:48:22 +01:00
parent ceee7cb0a6
commit 4b38294e92
No known key found for this signature in database
GPG Key ID: 67E38F7A8BA21772
1 changed files with 27 additions and 2 deletions

View File

@ -18,6 +18,7 @@ import (
"slices"
"strconv"
"strings"
"sync"
"syscall"
"time"
@ -52,6 +53,7 @@ import (
"github.com/containers/storage/pkg/unshare"
stypes "github.com/containers/storage/types"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/moby/sys/capability"
runcuser "github.com/moby/sys/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
@ -177,6 +179,18 @@ func getOverlayUpperAndWorkDir(options []string) (string, string, error) {
return upperDir, workDir, nil
}
// hasCapSysResource returns whether the current process has CAP_SYS_RESOURCE.
var hasCapSysResource = sync.OnceValues(func() (bool, error) {
currentCaps, err := capability.NewPid2(0)
if err != nil {
return false, err
}
if err = currentCaps.Load(); err != nil {
return false, err
}
return currentCaps.Get(capability.EFFECTIVE, capability.CAP_SYS_RESOURCE), nil
})
// Generate spec for a container
// Accepts a map of the container's dependencies
func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFuncRet func(), err error) {
@ -678,10 +692,21 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
nprocSet = true
}
}
needsClamping := false
if !nofileSet || !nprocSet {
needsClamping = isRunningInUserNs
if !needsClamping {
has, err := hasCapSysResource()
if err != nil {
return nil, nil, err
}
needsClamping = !has
}
}
if !nofileSet {
max := rlimT(define.RLimitDefaultValue)
current := rlimT(define.RLimitDefaultValue)
if isRunningInUserNs {
if needsClamping {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
@ -698,7 +723,7 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
if !nprocSet {
max := rlimT(define.RLimitDefaultValue)
current := rlimT(define.RLimitDefaultValue)
if isRunningInUserNs {
if needsClamping {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)