From 5ce91364b32a54d49e8b2668bbb9d1a00492228d Mon Sep 17 00:00:00 2001 From: Alexandr Morozov <lk4d4@docker.com> Date: Wed, 26 Nov 2014 23:00:13 -0800 Subject: [PATCH] Change path breakout detection logic in archive package Fixes #9375 Signed-off-by: Alexandr Morozov <lk4d4@docker.com> Conflicts: integration-cli/docker_cli_cp_test.go removed extra test --- archive/archive.go | 9 ++++++--- archive/diff.go | 12 +++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/archive/archive.go b/archive/archive.go index 13f447c..74c6014 100644 --- a/archive/archive.go +++ b/archive/archive.go @@ -473,10 +473,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 diff --git a/archive/diff.go b/archive/diff.go index e546763..80bb197 100644 --- a/archive/diff.go +++ b/archive/diff.go @@ -81,12 +81,14 @@ func UnpackLayer(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."):]