Change path breakout detection logic in archive package

Fixes #9375

Signed-off-by: Alexandr Morozov <lk4d4@docker.com>
This commit is contained in:
Alexandr Morozov 2014-11-26 23:00:13 -08:00
parent d3707a9411
commit be5bfbe221
3 changed files with 51 additions and 8 deletions

View File

@ -478,3 +478,41 @@ func TestCpVolumePath(t *testing.T) {
logDone("cp - volume path")
}
func TestCpToDot(t *testing.T) {
out, exitCode, err := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
if err != nil || exitCode != 0 {
t.Fatal("failed to create a container", out, err)
}
cleanedContainerID := stripTrailingCharacters(out)
defer deleteContainer(cleanedContainerID)
out, _, err = dockerCmd(t, "wait", cleanedContainerID)
if err != nil || stripTrailingCharacters(out) != "0" {
t.Fatal("failed to set up container", out, err)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer os.Chdir(cwd)
if err := os.Chdir(tmpdir); err != nil {
t.Fatal(err)
}
_, _, err = dockerCmd(t, "cp", cleanedContainerID+":/test", ".")
if err != nil {
t.Fatalf("couldn't docker cp to \".\" path: %s", err)
}
content, err := ioutil.ReadFile("./test")
if string(content) != "lololol\n" {
t.Fatal("Wrong content in copied file %q, should be %q", content, "lololol\n")
}
logDone("cp - to dot path")
}

View File

@ -530,10 +530,13 @@ loop:
}
}
// Prevent symlink breakout
path := filepath.Join(dest, hdr.Name)
if !strings.HasPrefix(path, dest) {
return breakoutError(fmt.Errorf("%q is outside of %q", path, dest))
rel, err := filepath.Rel(dest, path)
if err != nil {
return err
}
if strings.HasPrefix(rel, "..") {
return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest))
}
// If path exits we almost always just want to remove and replace it

View File

@ -92,12 +92,14 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
}
path := filepath.Join(dest, hdr.Name)
base := filepath.Base(path)
// Prevent symlink breakout
if !strings.HasPrefix(path, dest) {
return breakoutError(fmt.Errorf("%q is outside of %q", path, dest))
rel, err := filepath.Rel(dest, path)
if err != nil {
return err
}
if strings.HasPrefix(rel, "..") {
return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest))
}
base := filepath.Base(path)
if strings.HasPrefix(base, ".wh.") {
originalBase := base[len(".wh."):]