From 802c6c5c0d1dd384b649729d8b3d855114d0407e Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Wed, 11 Jan 2023 21:25:06 +0000 Subject: [PATCH] fuzzing: improve archive fuzzer Signed-off-by: AdamKorcz --- contrib/fuzz/archive_fuzzer.go | 35 +++++++- contrib/fuzz/oss_fuzz_build.sh | 1 - go.mod | 4 +- go.sum | 6 +- integration/client/go.mod | 4 +- integration/client/go.sum | 4 +- .../AdaLogics/go-fuzz-headers/consumer.go | 87 +++++++++++-------- .../AdaLogics/go-fuzz-headers/funcs.go | 14 +++ .../AdaLogics/go-fuzz-headers/sql.go | 14 +++ vendor/modules.txt | 3 +- 10 files changed, 123 insertions(+), 49 deletions(-) diff --git a/contrib/fuzz/archive_fuzzer.go b/contrib/fuzz/archive_fuzzer.go index a487c060e..cdb681bcc 100644 --- a/contrib/fuzz/archive_fuzzer.go +++ b/contrib/fuzz/archive_fuzzer.go @@ -74,8 +74,9 @@ func FuzzImportIndex(data []byte) int { if err != nil { return 0 } + var r *bytes.Reader ctx := context.Background() - r := bytes.NewReader(tarBytes) + r = bytes.NewReader(tarBytes) shouldRequireLayoutOrManifest, err := f.GetBool() if err != nil { return 0 @@ -98,7 +99,37 @@ func FuzzImportIndex(data []byte) int { } } if !hasLayoutOrManifest { - return 0 + var buf bytes.Buffer + tw := tar.NewWriter(&buf) + defer tw.Close() + tr := tar.NewReader(r) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return 0 + } + fileContents, err := io.ReadAll(tr) + if err != nil { + return 0 + } + tw.WriteHeader(hdr) + tw.Write(fileContents) + } + manifestFileContents, err := f.GetBytes() + if err != nil { + return 0 + } + tw.WriteHeader(&tar.Header{ + Name: "manifest.json", + Mode: 0644, + Size: int64(len(manifestFileContents)), + Typeflag: tar.TypeReg, + }) + tw.Write(manifestFileContents) + r = bytes.NewReader(buf.Bytes()) } } tmpdir, err := os.MkdirTemp("", "fuzzing-") diff --git a/contrib/fuzz/oss_fuzz_build.sh b/contrib/fuzz/oss_fuzz_build.sh index ce8ddefae..8484447c6 100755 --- a/contrib/fuzz/oss_fuzz_build.sh +++ b/contrib/fuzz/oss_fuzz_build.sh @@ -37,7 +37,6 @@ compile_fuzzers() { done } - # This is from https://github.com/AdamKorcz/instrumentation cd $SRC/instrumentation go run main.go $SRC/containerd/images diff --git a/go.mod b/go.mod index 75e41e4a7..a074936c1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/containerd/containerd go 1.18 require ( - github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830 + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 github.com/Microsoft/go-winio v0.6.0 github.com/Microsoft/hcsshim v0.10.0-rc.1 @@ -143,3 +143,5 @@ require ( ) replace github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809 + +replace github.com/AdaLogics/go-fuzz-headers => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf diff --git a/go.sum b/go.sum index 19af3f85f..f2d7c368a 100644 --- a/go.sum +++ b/go.sum @@ -43,11 +43,10 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830 h1:u8scGKApGy+gXpYDw2f+nh60R0FqCfrpDRIQki+5o3U= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf h1:EamsQRRH14elXDAofrOK5Ja6fDTJSrbKstpr1grrGX4= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf/go.mod h1:0vOOKsOMKPThRu9lQMAxcQ8D60f8U+wHXl07SyUw0+U= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -1274,6 +1273,7 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= diff --git a/integration/client/go.mod b/integration/client/go.mod index fead811c4..c74b897bc 100644 --- a/integration/client/go.mod +++ b/integration/client/go.mod @@ -3,7 +3,7 @@ module github.com/containerd/containerd/integration/client go 1.18 require ( - github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830 + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 github.com/Microsoft/hcsshim v0.10.0-rc.1 github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 @@ -77,3 +77,5 @@ replace ( // We use a replace to handle that until a new version is tagged. github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809 ) + +replace github.com/AdaLogics/go-fuzz-headers => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf diff --git a/integration/client/go.sum b/integration/client/go.sum index 4309b492d..4df402f17 100644 --- a/integration/client/go.sum +++ b/integration/client/go.sum @@ -377,10 +377,10 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830 h1:u8scGKApGy+gXpYDw2f+nh60R0FqCfrpDRIQki+5o3U= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf h1:EamsQRRH14elXDAofrOK5Ja6fDTJSrbKstpr1grrGX4= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf/go.mod h1:0vOOKsOMKPThRu9lQMAxcQ8D60f8U+wHXl07SyUw0+U= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= diff --git a/vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go b/vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go index 25f9a4174..ee373ed28 100644 --- a/vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go +++ b/vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go @@ -1,3 +1,17 @@ +// Copyright 2023 The go-fuzz-headers Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package gofuzzheaders import ( @@ -18,7 +32,10 @@ import ( securejoin "github.com/cyphar/filepath-securejoin" ) -var MaxTotalLen uint32 = 2000000 +var ( + MaxTotalLen uint32 = 2000000 + maxDepth = 100 +) func SetMaxTotalLen(newLen uint32) { MaxTotalLen = newLen @@ -32,6 +49,7 @@ type ConsumeFuzzer struct { NumberOfCalls int position uint32 fuzzUnexportedFields bool + curDepth int Funcs map[reflect.Type]reflect.Value } @@ -44,6 +62,7 @@ func NewConsumer(fuzzData []byte) *ConsumeFuzzer { data: fuzzData, dataTotal: uint32(len(fuzzData)), Funcs: make(map[reflect.Type]reflect.Value), + curDepth: 0, } } @@ -129,11 +148,18 @@ func (f *ConsumeFuzzer) setCustom(v reflect.Value) error { } func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error { + if f.curDepth >= maxDepth { + // return err or nil here? + return nil + } + f.curDepth++ + defer func() { f.curDepth-- }() + // We check if we should check for custom functions if customFunctions && e.IsValid() && e.CanAddr() { err := f.setCustom(e.Addr()) - if err == nil { - return nil + if err != nil { + return err } } @@ -367,13 +393,6 @@ func (f *ConsumeFuzzer) GetUint32() (uint32, error) { if err != nil { return 0, err } - littleEndian, err := f.GetBool() - if err != nil { - return 0, err - } - if littleEndian { - return binary.LittleEndian.Uint32(u32), nil - } return binary.BigEndian.Uint32(u32), nil } @@ -403,14 +422,14 @@ func (f *ConsumeFuzzer) GetBytes() ([]byte, error) { if f.position+length > MaxTotalLen { return nil, errors.New("created too large a string") } - byteBegin := f.position - 1 + byteBegin := f.position if byteBegin >= f.dataTotal { return nil, errors.New("not enough bytes to create byte array") } if length == 0 { return nil, errors.New("zero-length is not supported") } - if byteBegin+length >= f.dataTotal { + if byteBegin+length-1 >= f.dataTotal { return nil, errors.New("not enough bytes to create byte array") } if byteBegin+length < byteBegin { @@ -431,7 +450,7 @@ func (f *ConsumeFuzzer) GetString() (string, error) { if f.position > MaxTotalLen { return "nil", errors.New("created too large a string") } - byteBegin := f.position - 1 + byteBegin := f.position if byteBegin >= f.dataTotal { return "nil", errors.New("not enough bytes to create string") } @@ -463,6 +482,7 @@ func (f *ConsumeFuzzer) FuzzMap(m interface{}) error { } func returnTarBytes(buf []byte) ([]byte, error) { + return buf, nil // Count files var fileCounter int tr := tar.NewReader(bytes.NewReader(buf)) @@ -476,7 +496,7 @@ func returnTarBytes(buf []byte) ([]byte, error) { } fileCounter++ } - if fileCounter > 4 { + if fileCounter >= 1 { return buf, nil } return nil, fmt.Errorf("not enough files were created\n") @@ -547,6 +567,15 @@ func setTarHeaderTypeflag(hdr *tar.Header, f *ConsumeFuzzer) error { } func tooSmallFileBody(length uint32) bool { + if length < 2 { + return true + } + if length < 4 { + return true + } + if length < 10 { + return true + } if length < 100 { return true } @@ -589,30 +618,16 @@ func (f *ConsumeFuzzer) createTarFileBody() ([]byte, error) { return nil, errors.New("not enough bytes to create byte array") } - shouldUseLargeFileBody, err := f.GetBool() - if err != nil { - return nil, errors.New("not enough bytes to check long file body") - } - - if shouldUseLargeFileBody && tooSmallFileBody(length) { - return nil, errors.New("File body was too small") - } - // A bit of optimization to attempt to create a file body // when we don't have as many bytes left as "length" remainingBytes := f.dataTotal - f.position - if remainingBytes == 0 { + if remainingBytes <= 0 { return nil, errors.New("created too large a string") } - if remainingBytes < 50 { - length = length % remainingBytes - } else if f.dataTotal < 500 { - length = length % f.dataTotal - } if f.position+length > MaxTotalLen { return nil, errors.New("created too large a string") } - byteBegin := f.position - 1 + byteBegin := f.position if byteBegin >= f.dataTotal { return nil, errors.New("not enough bytes to create byte array") } @@ -641,18 +656,13 @@ func (f *ConsumeFuzzer) getTarFilename() (string, error) { // A bit of optimization to attempt to create a file name // when we don't have as many bytes left as "length" remainingBytes := f.dataTotal - f.position - if remainingBytes == 0 { + if remainingBytes <= 0 { return "nil", errors.New("created too large a string") } - if remainingBytes < 50 { - length = length % remainingBytes - } else if f.dataTotal < 500 { - length = length % f.dataTotal - } if f.position > MaxTotalLen { return "nil", errors.New("created too large a string") } - byteBegin := f.position - 1 + byteBegin := f.position if byteBegin >= f.dataTotal { return "nil", errors.New("not enough bytes to create string") } @@ -687,6 +697,7 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) { if err != nil { return returnTarBytes(buf.Bytes()) } + sec, err := f.GetInt() if err != nil { return returnTarBytes(buf.Bytes()) @@ -715,7 +726,7 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) { return returnTarBytes(buf.Bytes()) } } - return returnTarBytes(buf.Bytes()) + return buf.Bytes(), nil } // CreateFiles creates pseudo-random files in rootDir. diff --git a/vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go b/vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go index 40273c13a..8ca3a61b8 100644 --- a/vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go +++ b/vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go @@ -1,3 +1,17 @@ +// Copyright 2023 The go-fuzz-headers Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package gofuzzheaders import ( diff --git a/vendor/github.com/AdaLogics/go-fuzz-headers/sql.go b/vendor/github.com/AdaLogics/go-fuzz-headers/sql.go index 9290aac3a..2afd49f84 100644 --- a/vendor/github.com/AdaLogics/go-fuzz-headers/sql.go +++ b/vendor/github.com/AdaLogics/go-fuzz-headers/sql.go @@ -1,3 +1,17 @@ +// Copyright 2023 The go-fuzz-headers Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package gofuzzheaders import ( diff --git a/vendor/modules.txt b/vendor/modules.txt index 005e60391..9d52563f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,6 +1,6 @@ # cloud.google.com/go/compute/metadata v0.2.1 ## explicit; go 1.19 -# github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830 +# github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf ## explicit; go 1.18 github.com/AdaLogics/go-fuzz-headers # github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 @@ -798,3 +798,4 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml # github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809 +# github.com/AdaLogics/go-fuzz-headers => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf