diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index ac27e35c02..cdfba040a1 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -29,6 +29,7 @@ import ( "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/runconfig" + "github.com/docker/docker/volume" "github.com/docker/libnetwork" nwconfig "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/drivers/bridge" @@ -553,6 +554,12 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. return warnings, fmt.Errorf("Unknown runtime specified %s", hostConfig.Runtime) } + for dest := range hostConfig.Tmpfs { + if err := volume.ValidateTmpfsMountDestination(dest); err != nil { + return warnings, err + } + } + return warnings, nil } diff --git a/integration-cli/docker_cli_create_unix_test.go b/integration-cli/docker_cli_create_unix_test.go new file mode 100644 index 0000000000..1b0bb4a3dc --- /dev/null +++ b/integration-cli/docker_cli_create_unix_test.go @@ -0,0 +1,43 @@ +// +build !windows + +package main + +import ( + "strings" + + "github.com/go-check/check" +) + +// Test case for #30166 (target was not validated) +func (s *DockerSuite) TestCreateTmpfsMountsTarget(c *check.C) { + testRequires(c, DaemonIsLinux) + type testCase struct { + target string + expectedError string + } + cases := []testCase{ + { + target: ".", + expectedError: "mount path must be absolute", + }, + { + target: "foo", + expectedError: "mount path must be absolute", + }, + { + target: "/", + expectedError: "destination can't be '/'", + }, + { + target: "//", + expectedError: "destination can't be '/'", + }, + } + for _, x := range cases { + out, _, _ := dockerCmdWithError("create", "--tmpfs", x.target, "busybox", "sh") + if x.expectedError != "" && !strings.Contains(out, x.expectedError) { + c.Fatalf("mounting tmpfs over %q should fail with %q, but got %q", + x.target, x.expectedError, out) + } + } +} diff --git a/volume/validate.go b/volume/validate.go index 27a8c5d5b0..42396a0dad 100644 --- a/volume/validate.go +++ b/volume/validate.go @@ -91,6 +91,9 @@ func validateMountConfig(mnt *mount.Mount, options ...func(*validateOpts)) error if len(mnt.Source) != 0 { return &errMountConfig{mnt, errExtraField("Source")} } + if err := ValidateTmpfsMountDestination(mnt.Target); err != nil { + return &errMountConfig{mnt, err} + } if _, err := ConvertTmpfsOptions(mnt.TmpfsOptions, mnt.ReadOnly); err != nil { return &errMountConfig{mnt, err} } @@ -123,3 +126,15 @@ func validateAbsolute(p string) error { } return fmt.Errorf("invalid mount path: '%s' mount path must be absolute", p) } + +// ValidateTmpfsMountDestination validates the destination of tmpfs mount. +// Currently, we have only two obvious rule for validation: +// - path must not be "/" +// - path must be absolute +// We should add more rules carefully (#30166) +func ValidateTmpfsMountDestination(dest string) error { + if err := validateNotRoot(dest); err != nil { + return err + } + return validateAbsolute(dest) +}