Skip to content

Commit

Permalink
libcontainer:clean cached rlimit nofile in go runtime
Browse files Browse the repository at this point in the history
As reported in issue opencontainers#4195, the new version of go runtime will
cache rlimit-nofile. before executing exec, the rlimit-nofile
of the process will be updated with the cache. in runc, this will
cause the rlimit-nofile set by the parent process for the container
to become invalid. this can be solved by clearing the cache.

Signed-off-by: ls-ggg <[email protected]>
  • Loading branch information
ls-ggg authored and coolli committed Apr 18, 2024
1 parent 6a2813f commit f9f8abf
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
12 changes: 12 additions & 0 deletions libcontainer/setns_init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
"syscall"

"github.com/opencontainers/selinux/go-selinux"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -49,6 +50,17 @@ func (l *linuxSetnsInit) Init() error {
}
}
}

// Set RLIMIT_NOFILE again to clean the cache in go runtime
// The problem originates from https://github.com/golang/go/commit/f5eef58e4381259cbd84b3f2074c79607fb5c821
rlimit := syscall.Rlimit{}
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
return err
}
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
return err
}

if l.config.CreateConsole {
if err := setupConsole(l.consoleSocket, l.config, false); err != nil {
return err
Expand Down
20 changes: 15 additions & 5 deletions libcontainer/standard_init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import (
"fmt"
"os"
"os/exec"

"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
"syscall"

"github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/keys"
"github.com/opencontainers/runc/libcontainer/seccomp"
"github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/runc/libcontainer/utils"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)

type linuxStandardInit struct {
Expand Down Expand Up @@ -77,6 +77,16 @@ func (l *linuxStandardInit) Init() error {
}
}

// Set RLIMIT_NOFILE again to clean the cache in go runtime
// The problem originates from https://github.com/golang/go/commit/f5eef58e4381259cbd84b3f2074c79607fb5c821
rlimit := syscall.Rlimit{}
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
return err
}
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
return err
}

if err := setupNetwork(l.config); err != nil {
return err
}
Expand Down
22 changes: 22 additions & 0 deletions tests/integration/resources.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bats

load helpers

function setup() {
setup_busybox
}

function teardown() {
teardown_bundle
}

@test "runc run with RLIMIT_NOFILE" {
update_config '.process.args = ["/bin/sh", "-c", "ulimit -n"]'
update_config '.process.capabilities.bounding = ["CAP_SYS_RESOURCE"]'
update_config '.process.rlimits = [{"type": "RLIMIT_NOFILE", "hard": 10000, "soft": 10000}]'

runc run test_hello
[ "$status" -eq 0 ]

[[ "${output}" == "10000" ]]
}

0 comments on commit f9f8abf

Please sign in to comment.