From 632b314b239d1cd5e2498f198503a2983233a9f4 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 23 Apr 2016 08:00:57 -0700 Subject: [PATCH] Relative symlinks don't work with --device argument This fix tries to address the issue raised in #22271 where relative symlinks don't work with --device argument. Previously, the symlinks in --device was implemneted (#20684) with `os.Readlink()` which does not resolve if the linked target is a relative path. In this fix, `filepath.EvalSymlinks()` has been used which will reolve correctly with relative paths. An additional test case has been added to the existing `TestRunDeviceSymlink` to cover changes in this fix. This fix is related to #13840 and #20684, #22271. This fix fixes #22271. Signed-off-by: Yong Tang --- daemon/container_operations_unix.go | 2 +- integration-cli/docker_cli_run_unix_test.go | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 298193a5bd..84be5410d6 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -311,7 +311,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec // check if it is a symbolic link if src, e := os.Lstat(deviceMapping.PathOnHost); e == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink { - if linkedPathOnHost, e := os.Readlink(deviceMapping.PathOnHost); e == nil { + if linkedPathOnHost, e := filepath.EvalSymlinks(deviceMapping.PathOnHost); e == nil { resolvedPathOnHost = linkedPathOnHost } } diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 093f4ab99e..542e856182 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -1021,7 +1021,7 @@ func (s *DockerSuite) TestRunSeccompWithDefaultProfile(c *check.C) { c.Assert(strings.TrimSpace(out), checker.Equals, "unshare: unshare failed: Operation not permitted") } -// TestRunDeviceSymlink checks run with device that follows symlink (#13840) +// TestRunDeviceSymlink checks run with device that follows symlink (#13840 and #22271) func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) { testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm, SameHostDaemon) if _, err := os.Stat("/dev/zero"); err != nil { @@ -1048,6 +1048,14 @@ func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) { err = os.Symlink(tmpFile, symFile) c.Assert(err, checker.IsNil) + // Create a symbolic link to /dev/zero, this time with a relative path (#22271) + err = os.Symlink("zero", "/dev/symzero") + if err != nil { + c.Fatal("/dev/symzero creation failed") + } + // We need to remove this symbolic link here as it is created in /dev/, not temporary directory as above + defer os.Remove("/dev/symzero") + // md5sum of 'dd if=/dev/zero bs=4K count=8' is bb7df04e1b0a2570657527a7e108ae23 out, _ := dockerCmd(c, "run", "--device", symZero+":/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "bb7df04e1b0a2570657527a7e108ae23", check.Commentf("expected output bb7df04e1b0a2570657527a7e108ae23")) @@ -1056,6 +1064,10 @@ func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) { out, _, err = dockerCmdWithError("run", "--device", symFile+":/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") c.Assert(err, check.NotNil) c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "not a device node", check.Commentf("expected output 'not a device node'")) + + // md5sum of 'dd if=/dev/zero bs=4K count=8' is bb7df04e1b0a2570657527a7e108ae23 (this time check with relative path backed, see #22271) + out, _ = dockerCmd(c, "run", "--device", "/dev/symzero:/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") + c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "bb7df04e1b0a2570657527a7e108ae23", check.Commentf("expected output bb7df04e1b0a2570657527a7e108ae23")) } // TestRunPidsLimit makes sure the pids cgroup is set with --pids-limit