From 059e589c3427b1afa1b112acc931f59b5b063e16 Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Tue, 4 Nov 2014 15:23:21 -0800 Subject: [PATCH] Compute TarSum on storage of image layer content Now, newly created/imported layers will have the checksum of the layer diff computed and stored in the image json file. For now, it is not an error if the computed checksum does not match an existing checksum, only a warning message is logged. The eventual goal is to use the checksums in the image JSON to verify the integrity of the layer contents when doing `docker load` or `docker pull`, and error out if it does not match. Docker-DCO-1.1-Signed-off-by: Josh Hawn (github: jlhawn) --- graph/service.go | 1 + image/image.go | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/graph/service.go b/graph/service.go index 6f020e8d02..a27c9a8e38 100644 --- a/graph/service.go +++ b/graph/service.go @@ -150,6 +150,7 @@ func (s *TagStore) CmdLookup(job *engine.Job) engine.Status { out.Set("Os", image.OS) out.SetInt64("Size", image.Size) out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size) + out.Set("Checksum", image.Checksum) if _, err = out.WriteTo(job.Stdout); err != nil { return job.Error(err) } diff --git a/image/image.go b/image/image.go index dfa8e9a6e3..e58516bcb1 100644 --- a/image/image.go +++ b/image/image.go @@ -11,6 +11,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/tarsum" "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" ) @@ -32,6 +33,7 @@ type Image struct { Config *runconfig.Config `json:"config,omitempty"` Architecture string `json:"architecture,omitempty"` OS string `json:"os,omitempty"` + Checksum string `json:"checksum"` Size int64 graph Graph @@ -74,19 +76,43 @@ func LoadImage(root string) (*Image, error) { return img, nil } +// StoreImage stores file system layer data for the given image to the +// image's registered storage driver. Image metadata is stored in a file +// at the specified root directory. This function also computes the TarSum +// of `layerData` (currently using tarsum.dev). func StoreImage(img *Image, layerData archive.ArchiveReader, root string) error { // Store the layer var ( - size int64 - err error - driver = img.graph.Driver() + size int64 + err error + driver = img.graph.Driver() + layerTarSum tarsum.TarSum ) // If layerData is not nil, unpack it into the new layer if layerData != nil { - if size, err = driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil { + layerDataDecompressed, err := archive.DecompressStream(layerData) + if err != nil { return err } + + defer layerDataDecompressed.Close() + + if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.VersionDev); err != nil { + return err + } + + if size, err = driver.ApplyDiff(img.ID, img.Parent, layerTarSum); err != nil { + return err + } + + checksum := layerTarSum.Sum(nil) + + if img.Checksum != "" && img.Checksum != checksum { + log.Warn("image layer checksum mismatch: computed %q, expected %q", checksum, img.Checksum) + } + + img.Checksum = checksum } img.Size = size