瀏覽代碼

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 <akihiro.suda.cz@hco.ntt.co.jp>
Akihiro Suda 4 年之前
父節點
當前提交
227687f2ef
共有 2 個文件被更改,包括 61 次插入1 次删除
  1. 0 1
      integration/container/pidmode_linux_test.go
  2. 61 0
      rootless/specconv/specconv_linux.go

+ 0 - 1
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)

+ 61 - 0
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
 }