Skip to content

Commit 41a0424

Browse files
committed
Fuzzing: Add two more fuzzers
Signed-off-by: AdamKorcz <[email protected]>
1 parent 7d48917 commit 41a0424

3 files changed

Lines changed: 169 additions & 1 deletion

File tree

contrib/fuzz/archive_fuzzer.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
fuzz "github.com/AdaLogics/go-fuzz-headers"
2525

2626
"github.com/containerd/containerd/archive"
27+
"github.com/containerd/containerd/content/local"
28+
imageArchive "github.com/containerd/containerd/images/archive"
2729
)
2830

2931
// FuzzApply implements a fuzzer that applies
@@ -50,3 +52,25 @@ func FuzzApply(data []byte) int {
5052
}
5153
return 1
5254
}
55+
56+
// FuzzImportIndex implements a fuzzer
57+
// that targets archive.ImportIndex()
58+
func FuzzImportIndex(data []byte) int {
59+
f := fuzz.NewConsumer(data)
60+
tarBytes, err := f.TarBytes()
61+
if err != nil {
62+
return 0
63+
}
64+
ctx := context.Background()
65+
r := bytes.NewReader(tarBytes)
66+
tmpdir, err := ioutil.TempDir("", "fuzzing-")
67+
if err != nil {
68+
return 0
69+
}
70+
cs, err := local.NewStore(tmpdir)
71+
if err != nil {
72+
return 0
73+
}
74+
_, _ = imageArchive.ImportIndex(ctx, cs, r)
75+
return 1
76+
}

contrib/fuzz/content_fuzzer.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// +build gofuzz
2+
3+
/*
4+
Copyright The containerd Authors.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
// nolint: golint
17+
package fuzz
18+
19+
import (
20+
"bytes"
21+
"context"
22+
_ "crypto/sha256" // required by go-digest
23+
"fmt"
24+
"io/ioutil"
25+
"os"
26+
"path/filepath"
27+
"reflect"
28+
29+
fuzz "github.com/AdaLogics/go-fuzz-headers"
30+
digest "github.com/opencontainers/go-digest"
31+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32+
33+
"github.com/containerd/containerd/content"
34+
"github.com/containerd/containerd/content/local"
35+
)
36+
37+
// checkBlobPath performs some basic validation
38+
func checkBlobPath(dgst digest.Digest, root string) error {
39+
if err := dgst.Validate(); err != nil {
40+
return err
41+
}
42+
path := filepath.Join(root, "blobs", dgst.Algorithm().String(), dgst.Hex())
43+
_, err := os.Stat(path)
44+
if err != nil {
45+
return err
46+
}
47+
return nil
48+
}
49+
50+
// generateBlobs is a helper function to create random blobs
51+
func generateBlobs(f *fuzz.ConsumeFuzzer) (map[digest.Digest][]byte, error) {
52+
blobs := map[digest.Digest][]byte{}
53+
blobQty, err := f.GetInt()
54+
if err != nil {
55+
return blobs, err
56+
}
57+
maxsize := 4096
58+
nblobs := blobQty % maxsize
59+
60+
for i := 0; i < nblobs; i++ {
61+
digestBytes, err := f.GetBytes()
62+
if err != nil {
63+
return blobs, err
64+
}
65+
66+
dgst := digest.FromBytes(digestBytes)
67+
blobs[dgst] = digestBytes
68+
}
69+
70+
return blobs, nil
71+
}
72+
73+
// checkwrite is a wrapper around content.WriteBlob()
74+
func checkWrite(ctx context.Context, cs content.Store, dgst digest.Digest, p []byte) (digest.Digest, error) {
75+
if err := content.WriteBlob(ctx, cs, dgst.String(), bytes.NewReader(p),
76+
ocispec.Descriptor{Size: int64(len(p)), Digest: dgst}); err != nil {
77+
return dgst, err
78+
}
79+
return dgst, nil
80+
}
81+
82+
// populateBlobStore creates a bunch of blobs
83+
func populateBlobStore(ctx context.Context, cs content.Store, f *fuzz.ConsumeFuzzer) (map[digest.Digest][]byte, error) {
84+
blobs, err := generateBlobs(f)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
for dgst, p := range blobs {
90+
d, err := checkWrite(ctx, cs, dgst, p)
91+
_ = d
92+
if err != nil {
93+
return blobs, err
94+
}
95+
}
96+
return blobs, nil
97+
}
98+
99+
// FuzzCSWalk implements a fuzzer that targets contentStore.Walk()
100+
func FuzzCSWalk(data []byte) int {
101+
ctx := context.Background()
102+
expected := map[digest.Digest]struct{}{}
103+
found := map[digest.Digest]struct{}{}
104+
tmpdir, err := ioutil.TempDir("", "fuzzing-")
105+
if err != nil {
106+
return 0
107+
}
108+
cs, err := local.NewStore(tmpdir)
109+
if err != nil {
110+
return 0
111+
}
112+
113+
f := fuzz.NewConsumer(data)
114+
blobs, err := populateBlobStore(ctx, cs, f)
115+
_ = blobs
116+
if err != nil {
117+
return 0
118+
}
119+
120+
for dgst := range blobs {
121+
expected[dgst] = struct{}{}
122+
}
123+
124+
if err := cs.Walk(ctx, func(bi content.Info) error {
125+
found[bi.Digest] = struct{}{}
126+
err = checkBlobPath(bi.Digest, tmpdir)
127+
if err != nil {
128+
return err
129+
}
130+
return nil
131+
}); err != nil {
132+
return 0
133+
}
134+
if !reflect.DeepEqual(expected, found) {
135+
panic(fmt.Sprintf("%v != %v but should be equal", found, expected))
136+
}
137+
return 1
138+
}

contrib/fuzz/oss_fuzz_build.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
set -o nounset
18+
set -o pipefail
19+
set -o errexit
20+
set -x
21+
1722
cd "$(dirname "${BASH_SOURCE[0]}")"
1823
cd ../../
1924

@@ -26,7 +31,8 @@ compile_go_fuzzer github.com/containerd/containerd/remotes/docker FuzzFetcher fu
2631
compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzFiltersParse fuzz_filters_parse
2732
compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzPlatformsParse fuzz_platforms_parse
2833
compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzApply fuzz_apply
29-
34+
compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzImportIndex fuzz_import_index
35+
compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzCSWalk fuzz_cs_walk
3036

3137
# FuzzCreateContainer requires more setup than the fuzzers above.
3238
# We need the binaries from "make".

0 commit comments

Comments
 (0)