mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Follow symlink for --device argument.
Fixes: #13840 Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
parent
e330d0749c
commit
7ed569efdc
2 changed files with 50 additions and 4 deletions
|
@ -1106,7 +1106,16 @@ func killProcessDirectly(container *container.Container) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*configs.Device, err error) {
|
func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*configs.Device, err error) {
|
||||||
device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
|
resolvedPathOnHost := deviceMapping.PathOnHost
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
resolvedPathOnHost = linkedPathOnHost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device, err := devices.DeviceFromPath(resolvedPathOnHost, deviceMapping.CgroupPermissions)
|
||||||
// if there was no error, return the device
|
// if there was no error, return the device
|
||||||
if err == nil {
|
if err == nil {
|
||||||
device.Path = deviceMapping.PathInContainer
|
device.Path = deviceMapping.PathInContainer
|
||||||
|
@ -1118,10 +1127,10 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*con
|
||||||
if err == devices.ErrNotADevice {
|
if err == devices.ErrNotADevice {
|
||||||
|
|
||||||
// check if it is a directory
|
// check if it is a directory
|
||||||
if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
|
if src, e := os.Stat(resolvedPathOnHost); e == nil && src.IsDir() {
|
||||||
|
|
||||||
// mount the internal devices recursively
|
// mount the internal devices recursively
|
||||||
filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
|
filepath.Walk(resolvedPathOnHost, func(dpath string, f os.FileInfo, e error) error {
|
||||||
childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
|
childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
// ignore the device
|
// ignore the device
|
||||||
|
@ -1129,7 +1138,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*con
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the device to userSpecified devices
|
// add the device to userSpecified devices
|
||||||
childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
|
childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
|
||||||
devs = append(devs, childDevice)
|
devs = append(devs, childDevice)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -919,3 +919,40 @@ func (s *DockerSuite) TestRunSeccompWithDefaultProfile(c *check.C) {
|
||||||
c.Assert(err, checker.NotNil, check.Commentf(out))
|
c.Assert(err, checker.NotNil, check.Commentf(out))
|
||||||
c.Assert(strings.TrimSpace(out), checker.Equals, "unshare: unshare failed: Operation not permitted")
|
c.Assert(strings.TrimSpace(out), checker.Equals, "unshare: unshare failed: Operation not permitted")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRunDeviceSymlink checks run with device that follows symlink (#13840)
|
||||||
|
func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) {
|
||||||
|
testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm, SameHostDaemon)
|
||||||
|
if _, err := os.Stat("/dev/zero"); err != nil {
|
||||||
|
c.Skip("Host does not have /dev/zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary directory to create symlink
|
||||||
|
tmpDir, err := ioutil.TempDir("", "docker_device_follow_symlink_tests")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
// Create a symbolic link to /dev/zero
|
||||||
|
symZero := filepath.Join(tmpDir, "zero")
|
||||||
|
err = os.Symlink("/dev/zero", symZero)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Create a temporary file "temp" inside tmpDir, write some data to "tmpDir/temp",
|
||||||
|
// then create a symlink "tmpDir/file" to the temporary file "tmpDir/temp".
|
||||||
|
tmpFile := filepath.Join(tmpDir, "temp")
|
||||||
|
err = ioutil.WriteFile(tmpFile, []byte("temp"), 0666)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
symFile := filepath.Join(tmpDir, "file")
|
||||||
|
err = os.Symlink(tmpFile, symFile)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// 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"))
|
||||||
|
|
||||||
|
// symlink "tmpDir/file" to a file "tmpDir/temp" will result in an error as it is not a device.
|
||||||
|
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'"))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue