Skip to content

Commit

Permalink
chunked: improve detection of root directory path
Browse files Browse the repository at this point in the history
Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Dec 10, 2024
1 parent ebc19d3 commit a7188a7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
13 changes: 10 additions & 3 deletions pkg/chunked/storage_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,13 @@ func typeToOsMode(typ string) (os.FileMode, error) {
return 0, fmt.Errorf("unknown file type %q", typ)
}

// cleanAbsDirectory removes any ".." and "." from the path
// and ensures it starts with a "/". If the path refers to the root
// directory, it returns "/".
func cleanAbsDirectory(path string) string {
return filepath.Clean("/" + path)
}

func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, differOpts *graphdriver.DifferOptions) (graphdriver.DriverWithDifferOutput, error) {
defer c.layersCache.release()
defer func() {
Expand Down Expand Up @@ -1544,10 +1551,10 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff
}
}

r.Name = filepath.Clean(r.Name)
r.Name = cleanAbsDirectory(r.Name)
// do not modify the value of symlinks
if r.Linkname != "" && t != tar.TypeSymlink {
r.Linkname = filepath.Clean(r.Linkname)
r.Linkname = cleanAbsDirectory(r.Linkname)
}

if whiteoutConverter != nil {
Expand Down Expand Up @@ -1595,7 +1602,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff
}

case tar.TypeDir:
if r.Name == "" || r.Name == "." {
if r.Name == "/" {
output.RootDirMode = &mode
}
if err := safeMkdir(dirfd, mode, r.Name, r, options); err != nil {
Expand Down
36 changes: 36 additions & 0 deletions pkg/chunked/storage_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,39 @@ func TestTypeToOsMode(t *testing.T) {
})
}
}

func TestCleanAbsDirectory(t *testing.T) {
tests := []struct {
path string
expected string
}{
{"", "/"},
{"./", "/"},
{"../", "/"},
{"/../", "/"},
{"/./", "/"},
{"foo", "/foo"},
{"foo/bar", "/foo/bar"},
{"/foo/bar/../baz", "/foo/baz"},
{"/foo/./bar", "/foo/bar"},
{"/foo/bar/../../baz", "/baz"},
{"/././foo", "/foo"},
{"../foo", "/foo"},
{"./foo/bar/../..", "/"},
{"foo/..", "/"},
{"foo/../bar", "/bar"},
{"//foo//bar", "/foo/bar"},
{"foo/bar//baz/..", "/foo/bar"},
{"../..", "/"},
{".././..", "/"},
{"../../.", "/"},
{"/../../foo", "/foo"},
{"../foo/bar/../baz", "/foo/baz"},
{"../.././/.//../foo/./../bar/..", "/"},
{"a/../.././/.//../foo/./../bar/..", "/"},
}

for _, test := range tests {
assert.Equal(t, test.expected, cleanAbsDirectory(test.path), fmt.Sprintf("path %q failed", test.path))
}
}

0 comments on commit a7188a7

Please sign in to comment.