diff --git a/commands_test.go b/commands_test.go index 2c0e319787..b38ed33132 100644 --- a/commands_test.go +++ b/commands_test.go @@ -660,4 +660,41 @@ func TestCmdLogs(t *testing.T) { if err := cli.CmdLogs(globalRuntime.List()[0].ID); err != nil { t.Fatal(err) } + +// Expected behaviour: using / as a bind mount source should throw an error +func TestRunErrorBindMountRootSource(t *testing.T) { + + cli := NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr) + defer cleanup(globalRuntime) + + c := make(chan struct{}) + go func() { + defer close(c) + if err := cli.CmdRun("-v", "/:/tmp", unitTestImageID, "echo 'should fail'"); err == nil { + t.Fatal("should have failed to run when using / as a source for the bind mount") + } + }() + + setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + <-c + }) +} + +// Expected behaviour: error out when attempting to bind mount non-existing source paths +func TestRunErrorBindNonExistingSource(t *testing.T) { + + cli := NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr) + defer cleanup(globalRuntime) + + c := make(chan struct{}) + go func() { + defer close(c) + if err := cli.CmdRun("-v", "/i/dont/exist:/tmp", unitTestImageID, "echo 'should fail'"); err == nil { + t.Fatal("should have failed to run when using /i/dont/exist as a source for the bind mount") + } + }() + + setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + <-c + }) } diff --git a/container.go b/container.go index a22484c2d6..92e05283d1 100644 --- a/container.go +++ b/container.go @@ -251,6 +251,9 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, for bind := range flVolumes { arr := strings.Split(bind, ":") if len(arr) > 1 { + if arr[0] == "/" { + return nil, nil, cmd, fmt.Errorf("Invalid bind mount: source can't be '/'") + } dstDir := arr[1] flVolumes[dstDir] = struct{}{} binds = append(binds, bind) diff --git a/server.go b/server.go index 314df0256b..cbe7c6435c 100644 --- a/server.go +++ b/server.go @@ -1316,6 +1316,25 @@ func (srv *Server) RegisterLinks(name string, hostConfig *HostConfig) error { func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { runtime := srv.runtime container := runtime.Get(name) + + if hostConfig != nil { + for _, bind := range hostConfig.Binds { + splitBind := strings.Split(bind, ":") + source := splitBind[0] + + // refuse to bind mount "/" to the container + if source == "/" { + return fmt.Errorf("Invalid bind mount '%s' : source can't be '/'", bind) + } + + // ensure the source exists on the host + _, err := os.Stat(source) + if err != nil && os.IsNotExist(err) { + return fmt.Errorf("Invalid bind mount '%s' : source doesn't exist", bind) + } + } + } + if container == nil { return fmt.Errorf("No such container: %s", name) }