Skip to content

Commit

Permalink
Fuzzing: Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: AdamKorcz <adam@adalogics.com>
  • Loading branch information
AdamKorcz authored and Paulo Gomes committed Jan 10, 2022
1 parent 22c9f20 commit 945c9b1
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 0 deletions.
62 changes: 62 additions & 0 deletions fuzz/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
FROM golang:1.16-buster as builder
RUN set -eux; \
apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y \
clang \
curl \
vim

RUN git clone https://github.com/fluxcd/pkg /workspace
RUN mkdir /workspace/fuzzing


RUN go get -u github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest
RUN go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
RUN go get github.com/AdaLogics/go-fuzz-headers

RUN go get golang.org/x/sync

WORKDIR /workspace/fuzzing
COPY fuzz.go /workspace/fuzzing/
COPY conditions_fuzzer.go /workspace/runtime/conditions/
COPY tls_fuzzer.go /workspace/runtime/tls/
RUN cd /workspace/fuzzing && go mod init fuzzing && go mod tidy && go mod download && go mod tidy
RUN go mod download github.com/dvyukov/go-fuzz


# Build the fuzzers
RUN mkdir /fuzzers

RUN go-fuzz-build -libfuzzer -func=FuzzUntar\
&& clang -o /fuzzers/FuzzUntar reflect-fuzz.a \
-fsanitize=fuzzer
RUN go-fuzz-build -libfuzzer -func=FuzzLibGit2Error\
&& clang -o /fuzzers/FuzzLibGit2Error reflect-fuzz.a \
-fsanitize=fuzzer
RUN go-fuzz-build -libfuzzer -func=FuzzEventInfof\
&& clang -o /fuzzers/FuzzEventInfof reflect-fuzz.a \
-fsanitize=fuzzer

WORKDIR /workspace/runtime/tls
RUN go get github.com/AdaLogics/go-fuzz-headers
RUN go get github.com/dvyukov/go-fuzz/go-fuzz-dep
RUN go-fuzz-build -libfuzzer -func=FuzzTlsConfig\
&& clang -o /fuzzers/FuzzTlsConfig reflect-fuzz.a \
-fsanitize=fuzzer

WORKDIR /workspace/runtime/conditions
RUN go-fuzz-build -libfuzzer -func=FuzzGetterConditions\
&& clang -o /fuzzers/FuzzGetterConditions reflect-fuzz.a \
-fsanitize=fuzzer
RUN go-fuzz-build -libfuzzer -func=FuzzConditionsMatch\
&& clang -o /fuzzers/FuzzConditionsMatch reflect-fuzz.a \
-fsanitize=fuzzer
RUN go-fuzz-build -libfuzzer -func=FuzzPatchApply\
&& clang -o /fuzzers/FuzzPatchApply reflect-fuzz.a \
-fsanitize=fuzzer
RUN go-fuzz-build -libfuzzer -func=FuzzConditionsUnstructured\
&& clang -o /fuzzers/FuzzConditionsUnstructured reflect-fuzz.a \
-fsanitize=fuzzer

#RUN /fuzzers/FuzzLibGit2Error
161 changes: 161 additions & 0 deletions fuzz/conditions_fuzzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//go:build gofuzz
// +build gofuzz

/*
Copyright 2021 The Flux 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 conditions

import (
fuzz "github.com/AdaLogics/go-fuzz-headers"
"github.com/fluxcd/pkg/runtime/conditions/testdata"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

// FuzzGetterConditions implements a fuzzer that
// targets SetSummary()
func FuzzGetterConditions(data []byte) int {
f := fuzz.NewConsumer(data)

// Create slice of metav1.Condition
noOfConditions, err := f.GetInt()
if err != nil {
return 0
}
maxNoOfConditions := 30
conditions := make([]metav1.Condition, 0)

// Add Conditions in the slice
for i := 0; i < noOfConditions%maxNoOfConditions; i++ {
c := metav1.Condition{}
err = f.GenerateStruct(&c)
if err != nil {
return 0
}
conditions = append(conditions, c)
}
obj := &testdata.Fake{}
obj.SetConditions(conditions)

targetCondition, err := f.GetString()
if err != nil {
return 0
}

// Call the target
SetSummary(obj, targetCondition)
return 1
}

// FuzzConditionsMatch implements a fuzzer that
// that targets Match()
func FuzzConditionsMatch(data []byte) int {
f := fuzz.NewConsumer(data)
condition := metav1.Condition{}
err := f.GenerateStruct(&condition)
if err != nil {
return 0
}
m := MatchCondition(condition)

actual := metav1.Condition{}
err = f.GenerateStruct(&actual)
if err != nil {
return 0
}

// Call the target
_, _ = m.Match(actual)
return 1
}

// newGetter allows the fuzzer to create a Getter
// This is just a utility
func newGetter(f *fuzz.ConsumeFuzzer) (Getter, error) {
obj := &testdata.Fake{}
noOfConditions, err := f.GetInt()
if err != nil {
return obj, err
}
maxNoOfConditions := 30
conditions := make([]metav1.Condition, 0)
for i := 0; i < noOfConditions%maxNoOfConditions; i++ {
c := metav1.Condition{}
err = f.GenerateStruct(&c)
if err != nil {
return obj, err
}
conditions = append(conditions, c)
}

obj.SetConditions(conditions)
return obj, nil
}

// newSetter allows the fuzzer to create a Setter
// This is just a utility
func newSetter(f *fuzz.ConsumeFuzzer) (Setter, error) {
obj := &testdata.Fake{}
noOfConditions, err := f.GetInt()
if err != nil {
return obj, err
}
maxNoOfConditions := 30
conditions := make([]metav1.Condition, 0)
for i := 0; i < noOfConditions%maxNoOfConditions; i++ {
c := metav1.Condition{}
err = f.GenerateStruct(&c)
if err != nil {
return obj, err
}
conditions = append(conditions, c)
}
obj.SetConditions(conditions)
return obj, nil
}

// FuzzPatchApply implements a fuzzer that targets patch.Apply
func FuzzPatchApply(data []byte) int {
f := fuzz.NewConsumer(data)

before, err := newGetter(f)
if err != nil {
return 0
}
after, err := newGetter(f)
if err != nil {
return 0
}
patch := NewPatch(before, after)

setter, err := newSetter(f)
if err != nil {
return 0
}
_ = patch.Apply(setter)
return 1
}

// FuzzConditionsUnstructured implements a fuzzer
// that targets GetConditions()
func FuzzConditionsUnstructured(data []byte) int {
u := &unstructured.Unstructured{}
f := fuzz.NewConsumer(data)
err := f.GenerateStruct(u)
if err != nil {
return 0
}
g := UnstructuredGetter(u)
_ = g.GetConditions()
return 1
}
91 changes: 91 additions & 0 deletions fuzz/fuzz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//go:build gofuzz
// +build gofuzz

/*
Copyright 2021 The Flux 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 fuzzing

import (
"bytes"
"encoding/json"
"errors"
fuzz "github.com/AdaLogics/go-fuzz-headers"
"github.com/fluxcd/pkg/gitutil"
"github.com/fluxcd/pkg/runtime/events"
"github.com/fluxcd/pkg/untar"
"io"
corev1 "k8s.io/api/core/v1"
"net/http"
"net/http/httptest"
"os"
)

// FuzzUntar implements a fuzzer that
// targets untar.Untar()
func FuzzUntar(data []byte) int {
r := bytes.NewReader(data)
tmpDir, err := os.MkdirTemp("", "dir-")
if err != nil {
return 0
}
defer os.RemoveAll(tmpDir)
_, _ = untar.Untar(r, tmpDir)
return 1
}

// FuzzLibGit2Error implements a fuzzer that
// targets gitutil.LibGit2Error
func FuzzLibGit2Error(data []byte) int {
err := errors.New(string(data))
_ = gitutil.LibGit2Error(err)
return 1
}

// FuzzEventInfof implements a fuzzer that
// targets eventRecorder.EventInfof()
func FuzzEventInfof(data []byte) int {
f := fuzz.NewConsumer(data)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := io.ReadAll(r.Body)
if err != nil {
return
}

var payload events.Event
err = json.Unmarshal(b, &payload)
if err != nil {
return
}
}))
defer ts.Close()
eventRecorder, err := events.NewRecorder(ts.URL, "test-controller")
if err != nil {
return 0
}
eventRecorder.Client.RetryMax = 2
obj := corev1.ObjectReference{}
err = f.GenerateStruct(&obj)
if err != nil {
return 0
}
severity, err := f.GetString()
if err != nil {
return 0
}
reason, err := f.GetString()
if err != nil {
return 0
}
_ = eventRecorder.EventInfof(obj, nil, severity, reason, obj.Name)
return 1
}
34 changes: 34 additions & 0 deletions fuzz/tls_fuzzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build gofuzz
// +build gofuzz

/*
Copyright 2021 The Flux 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 tls

import (
fuzz "github.com/AdaLogics/go-fuzz-headers"
corev1 "k8s.io/api/core/v1"
)

// FuzzTlsConfig implements a fuzzer that
// targets ConfigFromSecret()
func FuzzTlsConfig(data []byte) int {
secret := &corev1.Secret{}
f := fuzz.NewConsumer(data)
err := f.GenerateStruct(secret)
if err != nil {
return 0
}
_, _ = ConfigFromSecret(secret)
return 1
}

0 comments on commit 945c9b1

Please sign in to comment.