From 38295d4b48fed3d9569100543a25e46b21deba46 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 24 Jul 2015 14:23:20 -0400 Subject: [PATCH] Have network files mounted read-only when -v parameter has 'ro' passed Have network files mounted read-only when mounted using the -v open and -v parameter has 'ro' passed. Signed-off-by: Stefan Berger Signed-off-by: Brian Goff --- daemon/container_unix.go | 18 ++++++-- integration-cli/docker_cli_run_test.go | 61 ++++++++++++++++++++------ integration-cli/docker_utils.go | 12 +++++ 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/daemon/container_unix.go b/daemon/container_unix.go index ef9820cd51..addc499b25 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -1128,28 +1128,40 @@ func (container *Container) networkMounts() []execdriver.Mount { } if container.ResolvConfPath != "" { label.Relabel(container.ResolvConfPath, container.MountLabel, mode) + writable := !container.hostConfig.ReadonlyRootfs + if m, exists := container.MountPoints["/etc/resolv.conf"]; exists { + writable = m.RW + } mounts = append(mounts, execdriver.Mount{ Source: container.ResolvConfPath, Destination: "/etc/resolv.conf", - Writable: !container.hostConfig.ReadonlyRootfs, + Writable: writable, Private: true, }) } if container.HostnamePath != "" { label.Relabel(container.HostnamePath, container.MountLabel, mode) + writable := !container.hostConfig.ReadonlyRootfs + if m, exists := container.MountPoints["/etc/hostname"]; exists { + writable = m.RW + } mounts = append(mounts, execdriver.Mount{ Source: container.HostnamePath, Destination: "/etc/hostname", - Writable: !container.hostConfig.ReadonlyRootfs, + Writable: writable, Private: true, }) } if container.HostsPath != "" { label.Relabel(container.HostsPath, container.MountLabel, mode) + writable := !container.hostConfig.ReadonlyRootfs + if m, exists := container.MountPoints["/etc/hosts"]; exists { + writable = m.RW + } mounts = append(mounts, execdriver.Mount{ Source: container.HostsPath, Destination: "/etc/hosts", - Writable: !container.hostConfig.ReadonlyRootfs, + Writable: writable, Private: true, }) } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 28b2b0e0e9..78f3c39108 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -2561,23 +2561,58 @@ func (s *DockerSuite) TestRunWriteFilteredProc(c *check.C) { func (s *DockerSuite) TestRunNetworkFilesBindMount(c *check.C) { testRequires(c, SameHostDaemon) - name := "test-nwfiles-mount" - - f, err := ioutil.TempFile("", name) - c.Assert(err, check.IsNil) - - filename := f.Name() - defer os.Remove(filename) expected := "test123" - err = ioutil.WriteFile(filename, []byte(expected), 0644) - c.Assert(err, check.IsNil) + filename := createTmpFile(c, expected) + defer os.Remove(filename) - var actual string - actual, _ = dockerCmd(c, "run", "-v", filename+":/etc/resolv.conf", "busybox", "cat", "/etc/resolv.conf") - if actual != expected { - c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual) + nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} + + for i := range nwfiles { + actual, _ := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "busybox", "cat", nwfiles[i]) + if actual != expected { + c.Fatalf("expected %s be: %q, but was: %q", nwfiles[i], expected, actual) + } + } +} + +func (s *DockerSuite) TestRunNetworkFilesBindMountRO(c *check.C) { + testRequires(c, SameHostDaemon) + + filename := createTmpFile(c, "test123") + defer os.Remove(filename) + + nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} + + for i := range nwfiles { + _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "busybox", "touch", nwfiles[i]) + if err == nil || exitCode == 0 { + c.Fatalf("run should fail because bind mount of %s is ro: exit code %d", nwfiles[i], exitCode) + } + } +} + +func (s *DockerSuite) TestRunNetworkFilesBindMountROFilesystem(c *check.C) { + testRequires(c, SameHostDaemon) + + filename := createTmpFile(c, "test123") + defer os.Remove(filename) + + nwfiles := []string{"/etc/resolv.conf", "/etc/hosts", "/etc/hostname"} + + for i := range nwfiles { + _, exitCode := dockerCmd(c, "run", "-v", filename+":"+nwfiles[i], "--read-only", "busybox", "touch", nwfiles[i]) + if exitCode != 0 { + c.Fatalf("run should not fail because %s is mounted writable on read-only root filesystem: exit code %d", nwfiles[i], exitCode) + } + } + + for i := range nwfiles { + _, exitCode, err := dockerCmdWithError("run", "-v", filename+":"+nwfiles[i]+":ro", "--read-only", "busybox", "touch", nwfiles[i]) + if err == nil || exitCode == 0 { + c.Fatalf("run should fail because %s is mounted read-only on read-only root filesystem: exit code %d", nwfiles[i], exitCode) + } } } diff --git a/integration-cli/docker_utils.go b/integration-cli/docker_utils.go index f2c7e4c48e..434e4efb95 100644 --- a/integration-cli/docker_utils.go +++ b/integration-cli/docker_utils.go @@ -1326,3 +1326,15 @@ func appendBaseEnv(env []string) []string { } return env } + +func createTmpFile(c *check.C, content string) string { + f, err := ioutil.TempFile("", "testfile") + c.Assert(err, check.IsNil) + + filename := f.Name() + + err = ioutil.WriteFile(filename, []byte(content), 0644) + c.Assert(err, check.IsNil) + + return filename +}