Make /proc, /sys, /dev readonly for readonly containers

If a container is read-only, also set /proc, /sys,
& /dev to read-only. This should apply to both privileged and
unprivileged containers.

Note that when /dev is read-only, device files may still be
written to. This change will simply prevent the device paths
from being modified, or performing mknod of new devices within
the /dev path.

Tests are included for all cases. Also adds a test to ensure
that /dev/pts is always mounted read/write, even in the case of a
read-write rootfs. The kernel restricts writes here naturally and
bad things will happen if we mount it ro.

Signed-off-by: Eric Windisch <eric@windisch.us>
Upstream-commit: 5400d8873f730e6099d29af49fe45931665c3b49
Component: engine
This commit is contained in:
Eric Windisch
2015-07-02 19:08:00 +00:00
parent fb10c26588
commit 793088ed0a
2 changed files with 45 additions and 6 deletions
@@ -2944,11 +2944,25 @@ func (s *DockerSuite) TestRunContainerWithWritableRootfs(c *check.C) {
func (s *DockerSuite) TestRunContainerWithReadonlyRootfs(c *check.C) {
testRequires(c, NativeExecDriver)
for _, f := range []string{"/file", "/etc/hosts", "/etc/resolv.conf", "/etc/hostname"} {
for _, f := range []string{"/file", "/etc/hosts", "/etc/resolv.conf", "/etc/hostname", "/proc/uptime", "/sys/kernel", "/dev/.dont.touch.me"} {
testReadOnlyFile(f, c)
}
}
func (s *DockerSuite) TestPermissionsPtsReadonlyRootfs(c *check.C) {
testRequires(c, NativeExecDriver)
// Ensure we have not broken writing /dev/pts
out, status := dockerCmd(c, "run", "--read-only", "--rm", "busybox", "mount")
if status != 0 {
c.Fatal("Could not obtain mounts when checking /dev/pts mntpnt.")
}
expected := "type devpts (rw,"
if !strings.Contains(string(out), expected) {
c.Fatalf("expected output to contain %s but contains %s", expected, out)
}
}
func testReadOnlyFile(filename string, c *check.C) {
testRequires(c, NativeExecDriver)
@@ -2960,6 +2974,15 @@ func testReadOnlyFile(filename string, c *check.C) {
if !strings.Contains(string(out), expected) {
c.Fatalf("expected output from failure to contain %s but contains %s", expected, out)
}
out, err = exec.Command(dockerBinary, "run", "--read-only", "--privileged", "--rm", "busybox", "touch", filename).CombinedOutput()
if err == nil {
c.Fatal("expected container to error on run with read only error")
}
expected = "Read-only file system"
if !strings.Contains(string(out), expected) {
c.Fatalf("expected output from failure to contain %s but contains %s", expected, out)
}
}
func (s *DockerSuite) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer(c *check.C) {