diff --git a/cmd/serve/docker/docker_test.go b/cmd/serve/docker/docker_test.go index 7cfa77560..ce7bb193a 100644 --- a/cmd/serve/docker/docker_test.go +++ b/cmd/serve/docker/docker_test.go @@ -245,6 +245,16 @@ func TestDockerPluginVolumeNameConfined(t *testing.T) { // The volume must not have been registered. _, err = drv.Get(&docker.GetRequest{Name: escape}) assert.Error(t, err) + + // A name that resolves to the base directory itself (empty or ".") + // must also be rejected, since mounting there would shadow every + // other volume. + for _, name := range []string{"", ".", filepath.Join("a", "..")} { + volReq.Name = name + err = drv.Create(volReq) + assertErrorContains(t, err, "resolves outside the base directory", + "name %q should be rejected", name) + } } // TestDockerPluginRestoreStateConfined checks that a persisted state file diff --git a/cmd/serve/docker/volume.go b/cmd/serve/docker/volume.go index e5b458a34..6555d5909 100644 --- a/cmd/serve/docker/volume.go +++ b/cmd/serve/docker/volume.go @@ -56,16 +56,18 @@ type VolInfo struct { } // volumeMountPath returns the mountpoint for a volume called name below -// root, together with whether that path stays confined within root. +// root, together with whether that path is a strict descendant of root. // // filepath.Join cleans its result, collapsing any ".." components in the // volume name, so a crafted name could otherwise resolve to an arbitrary -// host path outside root. Callers must reject names for which confined is -// false rather than creating a directory and mounting there. +// host path outside root, or to root itself (for an empty or "." name) +// where a mount would shadow every other volume. Callers must reject names +// for which confined is false rather than creating a directory and mounting +// there. func volumeMountPath(root, name string) (path string, confined bool) { path = filepath.Join(root, name) root = filepath.Clean(root) - return path, path == root || strings.HasPrefix(path, root+string(filepath.Separator)) + return path, strings.HasPrefix(path, root+string(filepath.Separator)) } func newVolume(ctx context.Context, name string, volOpt VolOpts, drv *Driver) (*Volume, error) {