runc:sync some patches

This commit is contained in:
zhongjiawei 2023-06-21 16:27:12 +08:00
parent c56a7bda7e
commit 8a63d08b9d
6 changed files with 250 additions and 2 deletions

View File

@ -1 +1 @@
1b26f86af8e3288668d096f778e0d33a0ecfcb03
10d460b661a3a68e9f83784e2bd115d807eda098

View File

@ -0,0 +1,104 @@
From acf196483ff8e2e5461a6c55ee64359863608b92 Mon Sep 17 00:00:00 2001
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Fri, 12 May 2023 16:04:11 -0700
Subject: [PATCH] libct: fix shared pidns detection
When someone is using libcontainer to start and kill containers from a
long lived process (i.e. the same process creates and removes the
container), initProcess.wait method is used, which has a kludge to work
around killing containers that do not have their own PID namespace.
The code that checks for own PID namespace is not entirely correct.
To be exact, it does not set sharePidns flag when the host/caller PID
namespace is implicitly used. As a result, the above mentioned kludge
does not work.
Fix the issue, add a test case (which fails without the fix).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/configs/namespaces_syscall.go | 12 ++++++++++++
libcontainer/container_linux.go | 3 +--
libcontainer/integration/exec_test.go | 20 +++++++++++++++-----
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/libcontainer/configs/namespaces_syscall.go b/libcontainer/configs/namespaces_syscall.go
index 0516dba8..543e059a 100644
--- a/libcontainer/configs/namespaces_syscall.go
+++ b/libcontainer/configs/namespaces_syscall.go
@@ -31,3 +31,15 @@ func (n *Namespaces) CloneFlags() uintptr {
}
return uintptr(flag)
}
+
+// IsPrivate tells whether the namespace of type t is configured as private
+// (i.e. it exists and is not shared).
+func (n Namespaces) IsPrivate(t NamespaceType) bool {
+ for _, v := range n {
+ if v.Type == t {
+ return v.Path == ""
+ }
+ }
+ // Not found, so implicitly sharing a parent namespace.
+ return false
+}
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index 1fc8feca..1a210fa2 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -555,7 +555,6 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, messageSockPa
nsMaps[ns.Type] = ns.Path
}
}
- _, sharePidns := nsMaps[configs.NEWPID]
data, err := c.bootstrapData(c.config.Namespaces.CloneFlags(), nsMaps, initStandard)
if err != nil {
return nil, err
@@ -600,7 +599,7 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, messageSockPa
container: c,
process: p,
bootstrapData: data,
- sharePidns: sharePidns,
+ sharePidns: !c.config.Namespaces.IsPrivate(configs.NEWPID),
}
c.initProcess = init
return init, nil
diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go
index 3da6d96c..1f19ced1 100644
--- a/libcontainer/integration/exec_test.go
+++ b/libcontainer/integration/exec_test.go
@@ -1456,16 +1456,26 @@ func TestPIDHost(t *testing.T) {
}
}
-func TestPIDHostInitProcessWait(t *testing.T) {
+func TestHostPidnsInitKill(t *testing.T) {
+ config := newTemplateConfig(t, nil)
+ // Implicitly use host pid ns.
+ config.Namespaces.Remove(configs.NEWPID)
+ testPidnsInitKill(t, config)
+}
+
+func TestSharedPidnsInitKill(t *testing.T) {
+ config := newTemplateConfig(t, nil)
+ // Explicitly use host pid ns.
+ config.Namespaces.Add(configs.NEWPID, "/proc/1/ns/pid")
+ testPidnsInitKill(t, config)
+}
+
+func testPidnsInitKill(t *testing.T, config *configs.Config) {
if testing.Short() {
return
}
- pidns := "/proc/1/ns/pid"
-
// Run a container with two long-running processes.
- config := newTemplateConfig(t, nil)
- config.Namespaces.Add(configs.NEWPID, pidns)
container, err := newContainer(t, config)
ok(t, err)
defer func() {
--
2.33.0

View File

@ -0,0 +1,97 @@
From 45abd12f084c62f3fbd24ab0fb0d3c1e3edf6ac7 Mon Sep 17 00:00:00 2001
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Tue, 4 Apr 2023 16:59:43 -0700
Subject: [PATCH] libct: fix a race with systemd removal
For a previous attempt to fix that (and added test cases), see commit
9087f2e827d971.
Alas, it's not always working because of cgroup directory TOCTOU.
To solve this and avoid the race, add an error _after_ the operation.
Implement it as a method that ignores the error that should be ignored.
Instead of currentStatus(), use faster runType(), since we are not
interested in Paused status here.
For Processes(), remove the pre-op check, and only use it after getting
an error, making the non-error path more straightforward.
For Signal(), add a second check after getting an error. The first check
is left as is because signalAllProcesses might print a warning if the
cgroup does not exist, and we'd like to avoid that.
This should fix an occasional failure like this one:
not ok 84 kill detached busybox
# (in test file tests/integration/kill.bats, line 27)
# `[ "$status" -eq 0 ]' failed
....
# runc kill test_busybox KILL (status=0):
# runc kill -a test_busybox 0 (status=1):
# time="2023-04-04T18:24:27Z" level=error msg="lstat /sys/fs/cgroup/devices/system.slice/runc-test_busybox.scope: no such file or directory"
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/container_linux.go | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index 1a210fa2..1189e5af 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -146,19 +146,27 @@ func (c *linuxContainer) OCIState() (*specs.State, error) {
return c.currentOCIState()
}
-func (c *linuxContainer) Processes() ([]int, error) {
- var pids []int
- status, err := c.currentStatus()
- if err != nil {
- return pids, err
+// ignoreCgroupError filters out cgroup-related errors that can be ignored,
+// because the container is stopped and its cgroup is gone.
+func (c *linuxContainer) ignoreCgroupError(err error) error {
+ if err == nil {
+ return nil
}
- // for systemd cgroup, the unit's cgroup path will be auto removed if container's all processes exited
- if status == Stopped && !c.cgroupManager.Exists() {
- return pids, nil
+ if errors.Is(err, os.ErrNotExist) && c.runType() == Stopped && !c.cgroupManager.Exists() {
+ return nil
}
+ return err
+}
- pids, err = c.cgroupManager.GetAllPids()
- if err != nil {
+// Processes returns the PIDs inside this container. The PIDs are in the
+// namespace of the calling process.
+//
+// Some of the returned PIDs may no longer refer to processes in the container,
+// unless the container state is PAUSED in which case every PID in the slice is
+// valid.
+func (c *linuxContainer) Processes() ([]int, error) {
+ pids, err := c.cgroupManager.GetAllPids()
+ if err = c.ignoreCgroupError(err); err != nil {
return nil, fmt.Errorf("unable to get all container pids: %w", err)
}
return pids, nil
@@ -382,11 +390,12 @@ func (c *linuxContainer) Signal(s os.Signal, all bool) error {
return err
}
if all {
- // for systemd cgroup, the unit's cgroup path will be auto removed if container's all processes exited
if status == Stopped && !c.cgroupManager.Exists() {
+ // Avoid calling signalAllProcesses which may print
+ // a warning trying to freeze a non-existing cgroup.
return nil
}
- return signalAllProcesses(c.cgroupManager, s)
+ return c.ignoreCgroupError(signalAllProcesses(c.cgroupManager, s))
}
// to avoid a PID reuse attack
if status == Running || status == Created || status == Paused {
--
2.33.0

View File

@ -0,0 +1,38 @@
From 2132cc52fbf68f9bfaf5dd18a1a5a25ecdd37929 Mon Sep 17 00:00:00 2001
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Thu, 23 Mar 2023 11:57:46 -0700
Subject: [PATCH] runc run: refuse a non-empty cgroup
Commit d08bc0c1b3bb2 ("runc run: warn on non-empty cgroup") introduced
a warning when a container is started in a non-empty cgroup. Such
configuration has lots of issues.
In addition to that, such configuration is not possible at all when
using the systemd cgroup driver.
As planned, let's promote this warning to an error, and fix the test
case accordingly.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/factory_linux.go | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go
index e6c71ac3..39fc3121 100644
--- a/libcontainer/factory_linux.go
+++ b/libcontainer/factory_linux.go
@@ -179,9 +179,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
return nil, fmt.Errorf("unable to get cgroup PIDs: %w", err)
}
if len(pids) != 0 {
- // TODO: return an error.
- logrus.Warnf("container's cgroup is not empty: %d process(es) found", len(pids))
- logrus.Warn("DEPRECATED: running container in a non-empty cgroup won't be supported in runc 1.2; https://github.com/opencontainers/runc/issues/3132")
+ return nil, fmt.Errorf("container's cgroup is not empty: %d process(es) found", len(pids))
}
}
--
2.33.0

View File

@ -3,7 +3,7 @@
Name: docker-runc
Version: 1.1.3
Release: 15
Release: 16
Summary: runc is a CLI tool for spawning and running containers according to the OCI specification.
License: ASL 2.0
@ -58,6 +58,12 @@ install -p -m 755 runc $RPM_BUILD_ROOT/%{_bindir}/runc
%{_bindir}/runc
%changelog
* Wed Jun 21 2023 zhongjiawei<zhongjiawei1@huawei.com> - 1.1.3-16
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:sync some patches
* Fri Jun 09 2023 zhongjiawei<zhongjiawei1@huawei.com> - 1.1.3-15
- Type:bugfix
- CVE:NA

View File

@ -36,3 +36,6 @@ patch/0037-runc-Fixed-init-state-error-variable.patch
patch/0038-runc-rootless-fix-sys-fs-cgroup-mounts.patch
patch/0039-runc-Prohibit-proc-and-sys-to-be-symlinks.patch
patch/0040-runc-modify-runc-make-command-to-satisfy-the-compile.patch
patch/0041-runc-libct-fix-shared-pidns-detection.patch
patch/0042-runc-libct-fix-a-race-with-systemd-removal.patch
patch/0043-runc-run-refuse-a-non-empty-cgroup.patch