From 2b72da8bf95e3e1afb361f8984584bcf0524cff3 Mon Sep 17 00:00:00 2001 From: Konstantin Baranov Date: Mon, 26 Oct 2020 18:02:52 -0700 Subject: [PATCH] Allow overriding mount options for /dev and /dev/pts This is useful to optionally set /dev ro,noexec. Treat /dev and /dev/pts the same as /proc and /sys. Make sure the Type is right though. Many config.json snippets on the Internet suggest /dev is tmpfs, not devtmpfs. --- runsc/boot/fs.go | 33 ++++++++++++++++++++------------- runsc/specutils/specutils.go | 8 +------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/runsc/boot/fs.go b/runsc/boot/fs.go index 9dd5b0184..a30fa198e 100644 --- a/runsc/boot/fs.go +++ b/runsc/boot/fs.go @@ -103,33 +103,28 @@ func addOverlay(ctx context.Context, conf *Config, lower *fs.Inode, name string, // mandatory mounts that are required by the OCI specification. func compileMounts(spec *specs.Spec) []specs.Mount { // Keep track of whether proc and sys were mounted. - var procMounted, sysMounted bool + var procMounted, sysMounted, devMounted, devptsMounted bool var mounts []specs.Mount - // Always mount /dev. - mounts = append(mounts, specs.Mount{ - Type: devtmpfs.Name, - Destination: "/dev", - }) - - mounts = append(mounts, specs.Mount{ - Type: devpts.Name, - Destination: "/dev/pts", - }) - // Mount all submounts from the spec. for _, m := range spec.Mounts { if !specutils.IsSupportedDevMount(m) { log.Warningf("ignoring dev mount at %q", m.Destination) continue } - mounts = append(mounts, m) switch filepath.Clean(m.Destination) { case "/proc": procMounted = true case "/sys": sysMounted = true + case "/dev": + m.Type = devtmpfs.Name + devMounted = true + case "/dev/pts": + m.Type = devpts.Name + devptsMounted = true } + mounts = append(mounts, m) } // Mount proc and sys even if the user did not ask for it, as the spec @@ -147,6 +142,18 @@ func compileMounts(spec *specs.Spec) []specs.Mount { Destination: "/sys", }) } + if !devMounted { + mandatoryMounts = append(mandatoryMounts, specs.Mount{ + Type: devtmpfs.Name, + Destination: "/dev", + }) + } + if !devptsMounted { + mandatoryMounts = append(mandatoryMounts, specs.Mount{ + Type: devpts.Name, + Destination: "/dev/pts", + }) + } // The mandatory mounts should be ordered right after the root, in case // there are submounts of these mandatory mounts already in the spec. diff --git a/runsc/specutils/specutils.go b/runsc/specutils/specutils.go index 5015c3a84..88b97f139 100644 --- a/runsc/specutils/specutils.go +++ b/runsc/specutils/specutils.go @@ -334,15 +334,9 @@ func IsSupportedDevMount(m specs.Mount) bool { var existingDevices = []string{ "/dev/fd", "/dev/stdin", "/dev/stdout", "/dev/stderr", "/dev/null", "/dev/zero", "/dev/full", "/dev/random", - "/dev/urandom", "/dev/shm", "/dev/pts", "/dev/ptmx", + "/dev/urandom", "/dev/shm", "/dev/ptmx", } dst := filepath.Clean(m.Destination) - if dst == "/dev" { - // OCI spec uses many different mounts for the things inside of '/dev'. We - // have a single mount at '/dev' that is always mounted, regardless of - // whether it was asked for, as the spec says we SHOULD. - return false - } for _, dev := range existingDevices { if dst == dev || strings.HasPrefix(dst, dev+"/") { return false