From 6498921a21e71d32a9797a2a65c49c96d3228243 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Tue, 4 Jun 2024 09:28:19 +0100 Subject: [PATCH] fix: Avoid cleaning paths in whiteout transformations Prior to this PR, when a tar file contains an entry prefixed with `./` that is processed by a whiteout transformation, the `./` prefix is lost. This loss of the prefix was due to the use of `filepath` functions that clean the resulting path. Instead, use `filepath.Split` and manual concatenation with filepath.Seperator` to avoid the clean. --- .../Test_WhiteoutRoundTrip/aufs.golden | Bin 4096 -> 4096 bytes .../Test_WhiteoutRoundTrip/overlayfs.golden | Bin 3584 -> 3584 bytes pkg/mutate/whiteout.go | 21 ++++++------------ pkg/mutate/whiteout_test.go | 2 +- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/pkg/mutate/testdata/Test_WhiteoutRoundTrip/aufs.golden b/pkg/mutate/testdata/Test_WhiteoutRoundTrip/aufs.golden index 8960745e4f3ddb59311661014ec7b13b8843f077..b7de931914a37f447692474cb69d27549dca754b 100644 GIT binary patch delta 57 zcmZorXi!+dF^P?BG7CrCgK!K9}@i6d!p3WqV9seuWDg7M@;#+1#Boc~z>iX;em delta 34 qcmZpWX^>gK!IGAllR9x>!sHYVV>V+Ga|Q+D$%%|9n;AL(vj70Q(h6As diff --git a/pkg/mutate/whiteout.go b/pkg/mutate/whiteout.go index 418e08e..47324bf 100644 --- a/pkg/mutate/whiteout.go +++ b/pkg/mutate/whiteout.go @@ -24,7 +24,6 @@ var errUnexpectedOpaque = errors.New("unexpected opaque marker") // scanAUFSWhiteouts reads a TAR stream, returning a map of :true for // directories in the tar that contain an AUFS .wh..wh..opq opaque directory // marker file, and a boolean indicating the presence of any .wh. markers. -// Note that paths returned are clean, per filepath.Clean. func scanAUFSWhiteouts(in io.Reader) (map[string]bool, bool, error) { opaquePaths := map[string]bool{} fileWhiteout := false @@ -40,10 +39,9 @@ func scanAUFSWhiteouts(in io.Reader) (map[string]bool, bool, error) { return nil, false, err } - base := filepath.Base(header.Name) + parent, base := filepath.Split(header.Name) if base == aufsOpaqueMarker { - parent := filepath.Dir(header.Name) opaquePaths[parent] = true } @@ -75,10 +73,7 @@ func whiteoutsToOverlayFS(in io.Reader, out io.Writer, opaquePaths map[string]bo // Must force to PAX format, to accommodate xattrs header.Format = tar.FormatPAX - clean := filepath.Clean(header.Name) - base := filepath.Base(header.Name) - parent := filepath.Dir(header.Name) - + parent, base := filepath.Split(header.Name) // Don't include .wh..wh..opq opaque directory markers in output. if base == aufsOpaqueMarker { // If we don't know the target should be opaque, then provided opaquePaths is incorrect. @@ -88,7 +83,7 @@ func whiteoutsToOverlayFS(in io.Reader, out io.Writer, opaquePaths map[string]bo continue } // Set overlayfs xattr on a dir that was previously found to contain a .wh..wh..opq marker. - if opq := opaquePaths[clean]; opq { + if opq := opaquePaths[header.Name]; opq { if header.PAXRecords == nil { header.PAXRecords = map[string]string{} } @@ -96,7 +91,7 @@ func whiteoutsToOverlayFS(in io.Reader, out io.Writer, opaquePaths map[string]bo } // Replace a `.wh.` marker with a char dev 0 at if strings.HasPrefix(base, aufsWhiteoutPrefix) { - target := filepath.Join(parent, strings.TrimPrefix(base, aufsWhiteoutPrefix)) + target := parent + strings.TrimPrefix(base, aufsWhiteoutPrefix) header.Name = target header.Typeflag = tar.TypeChar header.Devmajor = 0 @@ -146,12 +141,9 @@ func whiteoutsToAUFS(in io.Reader, out io.Writer) error { return err } // Write opaque marker file inside the directory. - // Disable gosec 305: File traversal when extracting zip/tar archive. - // We are modifying an existing tar stream. No extraction here. - //nolint:gosec if err := tw.WriteHeader(&tar.Header{ Typeflag: tar.TypeReg, - Name: filepath.Join(header.Name, aufsOpaqueMarker), + Name: strings.TrimSuffix(header.Name, string(filepath.Separator)) + string(filepath.Separator) + aufsOpaqueMarker, Size: 0, Mode: 0o600, Uid: header.Uid, @@ -168,8 +160,9 @@ func whiteoutsToAUFS(in io.Reader, out io.Writer) error { // as 0:0 char dev -> becomes .wh..wh. if header.Typeflag == tar.TypeChar && header.Devmajor == 0 && header.Devminor == 0 { + parent, base := filepath.Split(header.Name) header.Typeflag = tar.TypeReg - header.Name = filepath.Join(filepath.Dir(header.Name), aufsWhiteoutPrefix+filepath.Base(header.Name)) + header.Name = parent + aufsWhiteoutPrefix + base header.Size = 0 header.Mode = 0o600 } diff --git a/pkg/mutate/whiteout_test.go b/pkg/mutate/whiteout_test.go index e432b50..5e65fdf 100644 --- a/pkg/mutate/whiteout_test.go +++ b/pkg/mutate/whiteout_test.go @@ -42,7 +42,7 @@ func Test_scanAUFSOpaque(t *testing.T) { Hex: "da55812559dec81445c289c3832cee4a2f725b15aeb258791640185c3126b2bf", }), expectOpaque: map[string]bool{ - "dir": true, + "./dir/": true, }, expectFileWhiteout: true, },