isula-build/patch/0136-add-manifest.json-verification-before-loading-a-tar.patch

131 lines
4.8 KiB
Diff

From 373d9fb100649b74811acc73e6b7d67f539b561c Mon Sep 17 00:00:00 2001
From: daisicheng <daisicheng@huawei.com>
Date: Wed, 1 Feb 2023 15:12:33 +0800
Subject: [PATCH] add manifest.json verification before loading a tar
---
daemon/load.go | 45 +++++++++++++++++++++++++++++++++++++--------
daemon/load_test.go | 13 +++----------
2 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/daemon/load.go b/daemon/load.go
index c071374..69175d7 100644
--- a/daemon/load.go
+++ b/daemon/load.go
@@ -16,6 +16,7 @@ package daemon
import (
"context"
"os"
+ "strconv"
"strings"
"github.com/containers/image/v5/docker/tarfile"
@@ -175,25 +176,26 @@ func tryToParseImageFormatFromTarball(dataRoot string, opts *LoadOptions) ([]sin
systemContext.BigFilesTemporaryDir = tmpDir
// try docker format loading
- imagesInTar, err := getDockerRepoTagFromImageTar(systemContext, opts.path)
- if err == nil {
+ imagesInTar, errDockerFormat := getDockerRepoTagFromImageTar(systemContext, opts.path)
+ if errDockerFormat == nil {
logrus.Infof("Parse image successful with %q format", constant.DockerTransport)
opts.format = constant.DockerArchiveTransport
return imagesInTar, nil
}
- logrus.Warnf("Try to Parse image of docker format failed with error: %v", err)
+ logrus.Warnf("Try to Parse image of docker format failed with error: %v", errDockerFormat)
// try oci format loading
- imagesInTar, err = getOCIRepoTagFromImageTar(systemContext, opts.path)
- if err == nil {
+ imagesInTar, errOciFormat := getOCIRepoTagFromImageTar(systemContext, opts.path)
+ if errOciFormat == nil {
logrus.Infof("Parse image successful with %q format", constant.OCITransport)
opts.format = constant.OCIArchiveTransport
return imagesInTar, nil
}
- logrus.Warnf("Try to parse image of oci format failed with error: %v", err)
+ logrus.Warnf("Try to parse image of oci format failed with error: %v", errOciFormat)
- // record the last error
- return nil, errors.Wrap(err, "wrong image format detected from local tarball")
+ // record the error
+ return nil, errors.Errorf("wrong image format detected from local tarball: try docker format: %v,try oci format: %v",
+ errDockerFormat, errOciFormat)
}
func getDockerRepoTagFromImageTar(systemContext *types.SystemContext, path string) ([]singleImage, error) {
@@ -215,6 +217,9 @@ func getDockerRepoTagFromImageTar(systemContext *types.SystemContext, path strin
imagesInTar := make([]singleImage, 0, len(topLevelImageManifest))
for i, manifestItem := range topLevelImageManifest {
+ if err := checkManifestIsValid(systemContext, path, i); err != nil {
+ return nil, err
+ }
imageID, err := parseConfigID(manifestItem.Config)
if err != nil {
return nil, err
@@ -282,3 +287,27 @@ func getLoadedImageID(imageRef types.ImageReference, systemContext *types.System
return "@" + imageDigest.Encoded(), nil
}
+
+func checkManifestIsValid(systemContext *types.SystemContext, path string, manifestIndex int) error {
+ imageName := exporter.FormatTransport(constant.DockerArchiveTransport, path)
+ srcRef, err := alltransports.ParseImageName(imageName + ":@" + strconv.Itoa(manifestIndex))
+ if err != nil {
+ return errors.Wrap(err, "failed to parse image name of docker image format")
+ }
+
+ if srcRef == nil || systemContext == nil {
+ return errors.New("nil image reference or system context when loading image")
+ }
+
+ newImage, err := srcRef.NewImage(context.TODO(), systemContext)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err = newImage.Close(); err != nil {
+ logrus.Errorf("failed to close image: %v", err)
+ }
+ }()
+
+ return nil
+}
diff --git a/daemon/load_test.go b/daemon/load_test.go
index 5e1a42b..cecda36 100644
--- a/daemon/load_test.go
+++ b/daemon/load_test.go
@@ -271,7 +271,7 @@ func TestLoadSingleImage(t *testing.T) {
assert.ErrorContains(t, err, tc.errString)
return
}
- assert.ErrorContains(t, err, "failed to get the image")
+ assert.ErrorContains(t, err, "wrong image format detected from local tarball")
})
}
@@ -314,16 +314,9 @@ func TestLoadMultipleImages(t *testing.T) {
defer clean(dir)
path := dir.Join(loadedTarFile)
- repoTags, err := tryToParseImageFormatFromTarball(daemon.opts.DataRoot, &LoadOptions{path: path})
- assert.NilError(t, err)
- assert.Equal(t, repoTags[0].nameTag[0], "registry.example.com/sayhello:first")
- assert.Equal(t, repoTags[1].nameTag[0], "registry.example.com/sayhello:second")
- assert.Equal(t, repoTags[1].nameTag[1], "registry.example.com/sayhello:third")
- assert.Equal(t, len(repoTags[2].nameTag), 0)
-
req := &pb.LoadRequest{Path: path}
stream := &controlLoadServer{}
- err = daemon.backend.Load(req, stream)
- assert.ErrorContains(t, err, "failed to get the image")
+ err := daemon.backend.Load(req, stream)
+ assert.ErrorContains(t, err, "wrong image format detected from local tarball")
}
--
2.33.0