Skip to content

Commit

Permalink
Make manifest detection stricter
Browse files Browse the repository at this point in the history
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
  • Loading branch information
ktock committed Nov 18, 2021
1 parent 64cb046 commit e1b5341
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 6 deletions.
29 changes: 23 additions & 6 deletions store/refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/containerd/stargz-snapshotter/fs/source"
"github.com/containerd/stargz-snapshotter/util/containerdutil"
"github.com/containerd/stargz-snapshotter/util/lrucache"
digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -250,10 +252,27 @@ func fetchManifestPlatform(ctx context.Context, fetcher remotes.Fetcher, desc oc
var manifest ocispec.Manifest
switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
err = json.NewDecoder(r).Decode(&manifest)
p, err := ioutil.ReadAll(r)
if err != nil {
return ocispec.Manifest{}, err
}
if err := containerdutil.ValidateMediaType(p, desc.MediaType); err != nil {
return ocispec.Manifest{}, err
}
if err := json.Unmarshal(p, &manifest); err != nil {
return ocispec.Manifest{}, err
}
return manifest, nil
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
var index ocispec.Index
if err = json.NewDecoder(r).Decode(&index); err != nil {
p, err := ioutil.ReadAll(r)
if err != nil {
return ocispec.Manifest{}, err
}
if err := containerdutil.ValidateMediaType(p, desc.MediaType); err != nil {
return ocispec.Manifest{}, err
}
if err = json.Unmarshal(p, &index); err != nil {
return ocispec.Manifest{}, err
}
var target ocispec.Descriptor
Expand All @@ -273,9 +292,7 @@ func fetchManifestPlatform(ctx context.Context, fetcher remotes.Fetcher, desc oc
if !found {
return ocispec.Manifest{}, fmt.Errorf("no manifest found for platform")
}
manifest, err = fetchManifestPlatform(ctx, fetcher, target, platform)
default:
err = fmt.Errorf("unknown mediatype %q", desc.MediaType)
return fetchManifestPlatform(ctx, fetcher, target, platform)
}
return manifest, err
return ocispec.Manifest{}, fmt.Errorf("unknown mediatype %q", desc.MediaType)
}
48 changes: 48 additions & 0 deletions util/containerdutil/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package containerdutil
import (
"context"
"encoding/json"
"fmt"
"sort"

"github.com/containerd/containerd/content"
Expand All @@ -42,6 +43,9 @@ func ManifestDesc(ctx context.Context, provider content.Provider, image ocispec.
if err != nil {
return nil, err
}
if err := ValidateMediaType(p, desc.MediaType); err != nil {
return nil, err
}
var manifest ocispec.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
Expand Down Expand Up @@ -71,6 +75,9 @@ func ManifestDesc(ctx context.Context, provider content.Provider, image ocispec.
if err != nil {
return nil, err
}
if err := ValidateMediaType(p, desc.MediaType); err != nil {
return nil, err
}
var idx ocispec.Index
if err := json.Unmarshal(p, &idx); err != nil {
return nil, err
Expand Down Expand Up @@ -109,3 +116,44 @@ func ManifestDesc(ctx context.Context, provider content.Provider, image ocispec.
}
return m[0], nil
}

// Forked from github.com/containerd/containerd/images/image.go
// commit: a776a27af54a803657d002e7574a4425b3949f56

// unknownDocument represents a manifest, manifest list, or index that has not
// yet been validated.
type unknownDocument struct {
MediaType string `json:"mediaType,omitempty"`
Config json.RawMessage `json:"config,omitempty"`
Layers json.RawMessage `json:"layers,omitempty"`
Manifests json.RawMessage `json:"manifests,omitempty"`
FSLayers json.RawMessage `json:"fsLayers,omitempty"` // schema 1
}

// ValidateMediaType returns an error if the byte slice is invalid JSON or if
// the media type identifies the blob as one format but it contains elements of
// another format.
func ValidateMediaType(b []byte, mt string) error {
var doc unknownDocument
if err := json.Unmarshal(b, &doc); err != nil {
return err
}
if len(doc.FSLayers) != 0 {
return fmt.Errorf("media-type: schema 1 not supported")
}
switch mt {
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
if len(doc.Manifests) != 0 ||
doc.MediaType == images.MediaTypeDockerSchema2ManifestList ||
doc.MediaType == ocispec.MediaTypeImageIndex {
return fmt.Errorf("media-type: expected manifest but found index (%s)", mt)
}
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
if len(doc.Config) != 0 || len(doc.Layers) != 0 ||
doc.MediaType == images.MediaTypeDockerSchema2Manifest ||
doc.MediaType == ocispec.MediaTypeImageManifest {
return fmt.Errorf("media-type: expected index but found manifest (%s)", mt)
}
}
return nil
}

0 comments on commit e1b5341

Please sign in to comment.