runc/patch/0027-runc-libct-fix-shared-pidns-detection.patch
2023-07-28 09:46:10 +08:00

105 lines
3.5 KiB
Diff

From 43126d0dca0b76f8c07cff1d09c5fc013d5c3450 Mon Sep 17 00:00:00 2001
From: zhongjiawei <zhongjiawei1@huawei.com>
Date: Wed, 26 Jul 2023 16:52:56 +0800
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 0516dba..543e059 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 7141001..f56d73e 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -558,7 +558,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
@@ -603,7 +602,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 5c6272e..e999231 100644
--- a/libcontainer/integration/exec_test.go
+++ b/libcontainer/integration/exec_test.go
@@ -1404,16 +1404,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