From 7f2293859bd13e92782d01f58f63305b13e4d59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Mon, 24 May 2021 00:11:58 +0300 Subject: [PATCH] more robust manifest <-> tarball handling --- rootfs/rootfs.go | 25 ++++++++++++++++++++----- rootfs/rootfs_test.go | 7 ++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/rootfs/rootfs.go b/rootfs/rootfs.go index 773b808..9264a9d 100644 --- a/rootfs/rootfs.go +++ b/rootfs/rootfs.go @@ -15,13 +15,13 @@ import ( const ( _manifestJSON = "manifest.json" - _layerSuffix = "/layer.tar" + _tarSuffix = ".tar" _whReaddir = ".wh..wh..opq" _whPrefix = ".wh." ) var ( - errBadManifest = errors.New("bad or missing manifest.json") + errBadManifest = errors.New("bad manifest.json") ) type ( @@ -63,7 +63,7 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) { if err := dec.Decode(&manifest); err != nil { return fmt.Errorf("decode %s: %w", _manifestJSON, err) } - case strings.HasSuffix(hdr.Name, _layerSuffix): + case strings.HasSuffix(hdr.Name, _tarSuffix): here, err := rd.Seek(0, io.SeekCurrent) if err != nil { return err @@ -72,8 +72,8 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) { } } - if len(manifest) == 0 || len(layerOffsets) != len(manifest[0].Layers) { - return errBadManifest + if err := validateManifest(layerOffsets, manifest); err != nil { + return err } // enumerate layers the way they would be laid down in the image @@ -228,6 +228,21 @@ func whiteoutDirs(whreaddir map[string]int, nlayers int) []*tree { return ret } +// validateManifest +func validateManifest(layerOffsets map[string]int64, manifest dockerManifestJSON) error { + if len(manifest) == 0 { + return fmt.Errorf("empty or missing manifest") + } + + for _, layer := range manifest[0].Layers { + if _, ok := layerOffsets[layer]; !ok { + return fmt.Errorf("%s defined in manifest, missing in tarball", layer) + } + } + + return nil +} + // openTargz creates a tar reader from a targzip or tar. // // It will try to open a gzip stream, and, if that fails, silently fall back to diff --git a/rootfs/rootfs_test.go b/rootfs/rootfs_test.go index f22ba25..129f1ad 100644 --- a/rootfs/rootfs_test.go +++ b/rootfs/rootfs_test.go @@ -44,10 +44,15 @@ func TestRootFS(t *testing.T) { image: tarball{manifest{}}, want: []extractable{}, }, + { + name: "no manifest", + image: tarball{}, + wantErr: "empty or missing manifest", + }, { name: "missing layer", image: tarball{manifest{"layer0/layer.tar"}}, - wantErr: "bad or missing manifest.json", + wantErr: "layer0/layer.tar defined in manifest, missing in tarball", }, { name: "basic file overwrite, layer order mixed",