From debf52aa5b52c94393c2837355b3890ce86b9482 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 3 May 2024 12:12:46 -0700 Subject: [PATCH 1/7] deprecate libct.system.Execv This is not used since commit dac41717. It will be removed in v1.2.0 Signed-off-by: Kir Kolyshkin (cherry picked from commit dbd0c3349f7aab94563f9d6950e558ea547911f8) Signed-off-by: lifubang --- libcontainer/system/linux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcontainer/system/linux.go b/libcontainer/system/linux.go index e1d6eb18034..16edc6ba6d9 100644 --- a/libcontainer/system/linux.go +++ b/libcontainer/system/linux.go @@ -31,12 +31,12 @@ func (p ParentDeathSignal) Set() error { return SetParentDeathSignal(uintptr(p)) } +// Deprecated: Execv is not used in runc anymore, it will be removed in v1.2.0. func Execv(cmd string, args []string, env []string) error { name, err := exec.LookPath(cmd) if err != nil { return err } - return Exec(name, args, env) } From fbddb715edbbbd56eabecd6d289b734a17a0220a Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 3 May 2024 12:15:58 -0700 Subject: [PATCH 2/7] libct: fix a comment Do not refer to the function which was removed. Signed-off-by: Kir Kolyshkin (cherry picked from commit bac506463d48faca55baefbeb0e9ec7068088ad3) Signed-off-by: lifubang --- libcontainer/standard_init_linux.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index d1d94352f93..d9a6a224c5c 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -155,7 +155,8 @@ func (l *linuxStandardInit) Init() error { return &os.SyscallError{Syscall: "prctl(SET_NO_NEW_PRIVS)", Err: err} } } - // Tell our parent that we're ready to Execv. This must be done before the + + // Tell our parent that we're ready to exec. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { From 83ecd11c29ac8e6791c2f3d55aba64766f8e3524 Mon Sep 17 00:00:00 2001 From: lifubang Date: Tue, 30 Apr 2024 23:41:36 +0800 Subject: [PATCH 3/7] runc exec: setupRlimits after syscall.rlimit.init() completed Issue: /~https://github.com/opencontainers/runc/issues/4195 Since https://go-review.googlesource.com/c/go/+/476097, there is a get/set race between runc exec and syscall.rlimit.init, so we need to call setupRlimits after syscall.rlimit.init() completed. Signed-off-by: lifubang (cherry picked from commit a853a82677daf631d472b5c842d4182135cd1813) Signed-off-by: lifubang --- libcontainer/process_linux.go | 18 ++++++++++-------- libcontainer/setns_init_linux.go | 8 ++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index 0d9ceb9c98c..ac3b104ea02 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -152,11 +152,7 @@ func (p *setnsProcess) start() (retErr error) { } } } - // set rlimits, this has to be done here because we lose permissions - // to raise the limits once we enter a user-namespace - if err := setupRlimits(p.config.Rlimits, p.pid()); err != nil { - return fmt.Errorf("error setting rlimits for process: %w", err) - } + if err := utils.WriteJSON(p.messageSockPair.parent, p.config); err != nil { return fmt.Errorf("error writing config to pipe: %w", err) } @@ -164,8 +160,14 @@ func (p *setnsProcess) start() (retErr error) { ierr := parseSync(p.messageSockPair.parent, func(sync *syncT) error { switch sync.Type { case procReady: - // This shouldn't happen. - panic("unexpected procReady in setns") + // Set rlimits, this has to be done here because we lose permissions + // to raise the limits once we enter a user-namespace + if err := setupRlimits(p.config.Rlimits, p.pid()); err != nil { + return fmt.Errorf("error setting rlimits for ready process: %w", err) + } + + // Sync with child. + return writeSync(p.messageSockPair.parent, procRun) case procHooks: // This shouldn't happen. panic("unexpected procHooks in setns") @@ -495,7 +497,7 @@ func (p *initProcess) start() (retErr error) { return err } case procReady: - // set rlimits, this has to be done here because we lose permissions + // Set rlimits, this has to be done here because we lose permissions // to raise the limits once we enter a user-namespace if err := setupRlimits(p.config.Rlimits, p.pid()); err != nil { return fmt.Errorf("error setting rlimits for ready process: %w", err) diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index d1bb12273c0..5c8d1382fb7 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -61,6 +61,14 @@ func (l *linuxSetnsInit) Init() error { return err } } + + // Tell our parent that we're ready to exec. This must be done before the + // Seccomp rules have been applied, because we need to be able to read and + // write to a socket. + if err := syncParentReady(l.pipe); err != nil { + return fmt.Errorf("sync ready: %w", err) + } + if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { return err } From 42c2ab2b7cb93faaf874b585ac71f8548dfc5e34 Mon Sep 17 00:00:00 2001 From: lfbzhm Date: Fri, 10 May 2024 23:30:52 +0000 Subject: [PATCH 4/7] use go 1.18 in go.mod The complete generic features are supported since go 1.18 Signed-off-by: lfbzhm --- go.mod | 2 +- go.sum | 41 ----------------------------------------- 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/go.mod b/go.mod index f06efecd243..176be82e5a2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/opencontainers/runc -go 1.17 +go 1.18 require ( github.com/checkpoint-restore/go-criu/v5 v5.3.0 diff --git a/go.sum b/go.sum index 980b5d4ba86..600c2291daa 100644 --- a/go.sum +++ b/go.sum @@ -57,57 +57,16 @@ github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From d7a29a3b33675c57daa3134c01bfbc8b8375374c Mon Sep 17 00:00:00 2001 From: ls-ggg <335814617@qq.com> Date: Fri, 29 Mar 2024 18:12:08 +0800 Subject: [PATCH 5/7] libct: clean cached rlimit nofile in go runtime As reported in issue #4195, the new version(since 1.19) of go runtime will cache rlimit-nofile. Before executing execve, the rlimit-nofile of the process will be restored with the cache. In runc, this will cause the rlimit-nofile set by the parent process for the container to become invalid. It can be solved by clearing the cache. Signed-off-by: ls-ggg <335814617@qq.com> (cherry picked from commit f9f8abf3102e47f2fc3aa45bcd134e957da7de66) Signed-off-by: lifubang (cherry picked from commit da68c8e37b2f281c2105d6f7375d75d84db13a0f) Signed-off-by: lifubang --- libcontainer/init_linux.go | 16 ++++++++++++++++ libcontainer/setns_init_linux.go | 1 + libcontainer/system/rlimit_go119.go | 24 ++++++++++++++++++++++++ libcontainer/system/rlimit_stub.go | 6 ++++++ 4 files changed, 47 insertions(+) create mode 100644 libcontainer/system/rlimit_go119.go create mode 100644 libcontainer/system/rlimit_stub.go diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index d9f18139f54..58c742ac3e4 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -84,6 +84,13 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, if err := populateProcessEnvironment(config.Env); err != nil { return nil, err } + + // Clean the RLIMIT_NOFILE cache in go runtime. + // Issue: /~https://github.com/opencontainers/runc/issues/4195 + if containsRlimit(config.Rlimits, unix.RLIMIT_NOFILE) { + system.ClearRlimitNofileCache() + } + switch t { case initSetns: // mountFds must be nil in this case. We don't mount while doing runc exec. @@ -518,6 +525,15 @@ func setupRoute(config *configs.Config) error { return nil } +func containsRlimit(limits []configs.Rlimit, resource int) bool { + for _, rlimit := range limits { + if rlimit.Type == resource { + return true + } + } + return false +} + func setupRlimits(limits []configs.Rlimit, pid int) error { for _, rlimit := range limits { if err := unix.Prlimit(pid, rlimit.Type, &unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}, nil); err != nil { diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index 5c8d1382fb7..bb358901c34 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -48,6 +48,7 @@ func (l *linuxSetnsInit) Init() error { } } } + if l.config.CreateConsole { if err := setupConsole(l.consoleSocket, l.config, false); err != nil { return err diff --git a/libcontainer/system/rlimit_go119.go b/libcontainer/system/rlimit_go119.go new file mode 100644 index 00000000000..e3c2efeb16f --- /dev/null +++ b/libcontainer/system/rlimit_go119.go @@ -0,0 +1,24 @@ +//go:build go1.19 + +package system + +import ( + "sync/atomic" + "syscall" + + _ "unsafe" // for go:linkname +) + +//go:linkname syscallOrigRlimitNofile syscall.origRlimitNofile +var syscallOrigRlimitNofile atomic.Pointer[syscall.Rlimit] + +// As reported in issue #4195, the new version of go runtime(since 1.19) +// will cache rlimit-nofile. Before executing execve, the rlimit-nofile +// of the process will be restored with the cache. In runc, this will +// cause the rlimit-nofile setting by the parent process for the container +// to become invalid. It can be solved by clearing this cache. But +// unfortunately, go stdlib doesn't provide such function, so we need to +// link to the private var `origRlimitNofile` in package syscall to hack. +func ClearRlimitNofileCache() { + syscallOrigRlimitNofile.Store(nil) +} diff --git a/libcontainer/system/rlimit_stub.go b/libcontainer/system/rlimit_stub.go new file mode 100644 index 00000000000..1b37dc5720c --- /dev/null +++ b/libcontainer/system/rlimit_stub.go @@ -0,0 +1,6 @@ +//go:build !go1.19 + +package system + +func ClearRlimitNofileCache() { +} From 2992049dc31cda18012dc16a818ee4d99b547c3a Mon Sep 17 00:00:00 2001 From: lifubang Date: Wed, 1 May 2024 00:25:49 +0800 Subject: [PATCH 6/7] update/add some tests for rlimit issues: /~https://github.com/opencontainers/runc/issues/4195 /~https://github.com/opencontainers/runc/pull/4265#discussion_r1588599809 Signed-off-by: lifubang (cherry picked from commit 4ea0bf88fda72a1aeb34d443649b6d3d1e1c6baf) Signed-off-by: lfbzhm --- libcontainer/integration/exec_test.go | 6 +- tests/integration/rlimits.bats | 88 +++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tests/integration/rlimits.bats diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index 670b33fcbb3..568bb637916 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -135,11 +135,13 @@ func testRlimit(t *testing.T, userns bool) { config := newTemplateConfig(t, &tParam{userns: userns}) - // ensure limit is lower than what the config requests to test that in a user namespace + // Ensure limit is lower than what the config requests to test that in a user namespace // the Setrlimit call happens early enough that we still have permissions to raise the limit. + // Do not change the Cur value to be equal to the Max value, please see: + // /~https://github.com/opencontainers/runc/pull/4265#discussion_r1589666444 ok(t, unix.Setrlimit(unix.RLIMIT_NOFILE, &unix.Rlimit{ Max: 1024, - Cur: 1024, + Cur: 512, })) out := runContainerOk(t, config, "/bin/sh", "-c", "ulimit -n") diff --git a/tests/integration/rlimits.bats b/tests/integration/rlimits.bats new file mode 100644 index 00000000000..356a7871069 --- /dev/null +++ b/tests/integration/rlimits.bats @@ -0,0 +1,88 @@ +#!/usr/bin/env bats + +load helpers + +function setup() { + # Do not change the Cur value to be equal to the Max value + # Because in some environments, the soft and hard nofile limit have the same value. + [ $EUID -eq 0 ] && prlimit --nofile=1024:65536 -p $$ + setup_busybox +} + +function teardown() { + teardown_bundle +} + +# Set and check rlimit_nofile for runc run. Arguments are: +# $1: soft limit; +# $2: hard limit. +function run_check_nofile() { + soft="$1" + hard="$2" + update_config ".process.rlimits = [{\"type\": \"RLIMIT_NOFILE\", \"soft\": ${soft}, \"hard\": ${hard}}]" + update_config '.process.args = ["/bin/sh", "-c", "ulimit -n; ulimit -H -n"]' + + runc run test_rlimit + [ "$status" -eq 0 ] + [[ "${lines[0]}" == "${soft}" ]] + [[ "${lines[1]}" == "${hard}" ]] +} + +# Set and check rlimit_nofile for runc exec. Arguments are: +# $1: soft limit; +# $2: hard limit. +function exec_check_nofile() { + soft="$1" + hard="$2" + update_config ".process.rlimits = [{\"type\": \"RLIMIT_NOFILE\", \"soft\": ${soft}, \"hard\": ${hard}}]" + + runc run -d --console-socket "$CONSOLE_SOCKET" test_rlimit + [ "$status" -eq 0 ] + + runc exec test_rlimit /bin/sh -c "ulimit -n; ulimit -H -n" + [ "$status" -eq 0 ] + [[ "${lines[0]}" == "${soft}" ]] + [[ "${lines[1]}" == "${hard}" ]] +} + +@test "runc run with RLIMIT_NOFILE(The same as system's hard value)" { + hard=$(ulimit -n -H) + soft="$hard" + run_check_nofile "$soft" "$hard" +} + +@test "runc run with RLIMIT_NOFILE(Bigger than system's hard value)" { + requires root + limit=$(ulimit -n -H) + soft=$((limit + 1)) + hard=$soft + run_check_nofile "$soft" "$hard" +} + +@test "runc run with RLIMIT_NOFILE(Smaller than system's hard value)" { + limit=$(ulimit -n -H) + soft=$((limit - 1)) + hard=$soft + run_check_nofile "$soft" "$hard" +} + +@test "runc exec with RLIMIT_NOFILE(The same as system's hard value)" { + hard=$(ulimit -n -H) + soft="$hard" + exec_check_nofile "$soft" "$hard" +} + +@test "runc exec with RLIMIT_NOFILE(Bigger than system's hard value)" { + requires root + limit=$(ulimit -n -H) + soft=$((limit + 1)) + hard=$soft + exec_check_nofile "$soft" "$hard" +} + +@test "runc exec with RLIMIT_NOFILE(Smaller than system's hard value)" { + limit=$(ulimit -n -H) + soft=$((limit - 1)) + hard=$soft + exec_check_nofile "$soft" "$hard" +} From c918058bb76c880ea56b6430d7a2a629ec47a719 Mon Sep 17 00:00:00 2001 From: lifubang Date: Thu, 16 May 2024 20:34:43 +0800 Subject: [PATCH 7/7] fix comments for ClearRlimitNofileCache Signed-off-by: lifubang (cherry picked from commit a35f7d80931192c50ea15d688afd54f45c7fb7fd) Signed-off-by: lifubang --- libcontainer/system/rlimit_go119.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libcontainer/system/rlimit_go119.go b/libcontainer/system/rlimit_go119.go index e3c2efeb16f..a68c8ca6038 100644 --- a/libcontainer/system/rlimit_go119.go +++ b/libcontainer/system/rlimit_go119.go @@ -12,13 +12,14 @@ import ( //go:linkname syscallOrigRlimitNofile syscall.origRlimitNofile var syscallOrigRlimitNofile atomic.Pointer[syscall.Rlimit] -// As reported in issue #4195, the new version of go runtime(since 1.19) -// will cache rlimit-nofile. Before executing execve, the rlimit-nofile -// of the process will be restored with the cache. In runc, this will -// cause the rlimit-nofile setting by the parent process for the container -// to become invalid. It can be solved by clearing this cache. But -// unfortunately, go stdlib doesn't provide such function, so we need to -// link to the private var `origRlimitNofile` in package syscall to hack. +// ClearRlimitNofileCache is to clear go runtime's nofile rlimit cache. func ClearRlimitNofileCache() { + // As reported in issue #4195, the new version of go runtime(since 1.19) + // will cache rlimit-nofile. Before executing execve, the rlimit-nofile + // of the process will be restored with the cache. In runc, this will + // cause the rlimit-nofile setting by the parent process for the container + // to become invalid. It can be solved by clearing this cache. But + // unfortunately, go stdlib doesn't provide such function, so we need to + // link to the private var `origRlimitNofile` in package syscall to hack. syscallOrigRlimitNofile.Store(nil) }