From 227687f2efb848f06e756bc0f6b470b05f7d502a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 19 Jan 2021 14:12:43 +0900 Subject: [PATCH] rootless: support --pid=host Fix #41457 related: https://github.com/containers/podman/blob/v3.0.0-rc1/pkg/specgen/generate/oci.go#L248-L257 Signed-off-by: Akihiro Suda --- integration/container/pidmode_linux_test.go | 1 - rootless/specconv/specconv_linux.go | 61 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/integration/container/pidmode_linux_test.go b/integration/container/pidmode_linux_test.go index a83b527a27..003192ac05 100644 --- a/integration/container/pidmode_linux_test.go +++ b/integration/container/pidmode_linux_test.go @@ -15,7 +15,6 @@ import ( func TestPidHost(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.IsRemoteDaemon()) - skip.If(t, testEnv.IsRootless, "https://github.com/moby/moby/issues/41457") hostPid, err := os.Readlink("/proc/1/ns/pid") assert.NilError(t, err) diff --git a/rootless/specconv/specconv_linux.go b/rootless/specconv/specconv_linux.go index 9416076fb7..5b461bb157 100644 --- a/rootless/specconv/specconv_linux.go +++ b/rootless/specconv/specconv_linux.go @@ -2,7 +2,10 @@ package specconv // import "github.com/docker/docker/rootless/specconv" import ( "io/ioutil" + "os" + "path" "strconv" + "strings" specs "github.com/opencontainers/runtime-spec/specs-go" ) @@ -10,6 +13,7 @@ import ( // ToRootless converts spec to be compatible with "rootless" runc. // * Remove non-supported cgroups // * Fix up OOMScoreAdj +// * Fix up /proc if --pid=host // // v2Controllers should be non-nil only if running with v2 and systemd. func ToRootless(spec *specs.Spec, v2Controllers []string) error { @@ -70,5 +74,62 @@ func toRootless(spec *specs.Spec, v2Controllers []string, currentOOMScoreAdj int if spec.Process.OOMScoreAdj != nil && *spec.Process.OOMScoreAdj < currentOOMScoreAdj { *spec.Process.OOMScoreAdj = currentOOMScoreAdj } + + // Fix up /proc if --pid=host + pidHost, err := isPidHost(spec) + if err != nil { + return err + } + if !pidHost { + return nil + } + return bindMountHostProcfs(spec) +} + +func isPidHost(spec *specs.Spec) (bool, error) { + for _, ns := range spec.Linux.Namespaces { + if ns.Type == specs.PIDNamespace { + if ns.Path == "" { + return false, nil + } + pidNS, err := os.Readlink(ns.Path) + if err != nil { + return false, err + } + selfPidNS, err := os.Readlink("/proc/self/ns/pid") + if err != nil { + return false, err + } + return pidNS == selfPidNS, nil + } + } + return true, nil +} + +func bindMountHostProcfs(spec *specs.Spec) error { + // Replace procfs mount with rbind + // https://github.com/containers/podman/blob/v3.0.0-rc1/pkg/specgen/generate/oci.go#L248-L257 + for i, m := range spec.Mounts { + if path.Clean(m.Destination) == "/proc" { + newM := specs.Mount{ + Destination: "/proc", + Type: "bind", + Source: "/proc", + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + spec.Mounts[i] = newM + } + } + + // Remove ReadonlyPaths for /proc/* + newROP := spec.Linux.ReadonlyPaths[:0] + for _, s := range spec.Linux.ReadonlyPaths { + s = path.Clean(s) + if !strings.HasPrefix(s, "/proc/") { + newROP = append(newROP, s) + } + } + spec.Linux.ReadonlyPaths = newROP + return nil }