!150 runc:sync some patches
From: @zhong-jiawei-1 Reviewed-by: @zhangsong234, @duguhaotian Signed-off-by: @duguhaotian
This commit is contained in:
commit
f85ad401ea
@ -1 +1 @@
|
||||
1b26f86af8e3288668d096f778e0d33a0ecfcb03
|
||||
10d460b661a3a68e9f83784e2bd115d807eda098
|
||||
|
||||
104
patch/0041-runc-libct-fix-shared-pidns-detection.patch
Normal file
104
patch/0041-runc-libct-fix-shared-pidns-detection.patch
Normal 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
|
||||
|
||||
97
patch/0042-runc-libct-fix-a-race-with-systemd-removal.patch
Normal file
97
patch/0042-runc-libct-fix-a-race-with-systemd-removal.patch
Normal 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
|
||||
|
||||
38
patch/0043-runc-run-refuse-a-non-empty-cgroup.patch
Normal file
38
patch/0043-runc-run-refuse-a-non-empty-cgroup.patch
Normal 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user