From c9b1b2fd5b6ec9d434a4baf3c091a31bfa039934 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Fri, 13 Aug 2021 22:16:37 +0100 Subject: [PATCH] Fuzzing: Add fuzzer Signed-off-by: AdamKorcz --- contrib/fuzz/containerd_import_fuzzer.go | 77 ++++++++++++++++++++++++ contrib/fuzz/oss_fuzz_build.sh | 26 +++++++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 contrib/fuzz/containerd_import_fuzzer.go diff --git a/contrib/fuzz/containerd_import_fuzzer.go b/contrib/fuzz/containerd_import_fuzzer.go new file mode 100644 index 000000000..13cd555db --- /dev/null +++ b/contrib/fuzz/containerd_import_fuzzer.go @@ -0,0 +1,77 @@ +// +build gofuzz + +/* + Copyright The containerd 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 fuzz + +import ( + "bytes" + "context" + + fuzz "github.com/AdaLogics/go-fuzz-headers" + + "github.com/containerd/containerd" + _ "github.com/containerd/containerd/cmd/containerd" + "github.com/containerd/containerd/cmd/containerd/command" + "github.com/containerd/containerd/namespaces" +) + +const ( + defaultRoot = "/var/lib/containerd" + defaultState = "/tmp/containerd" + defaultAddress = "/tmp/containerd/containerd.sock" +) + +func init() { + args := []string{"--log-level", "debug"} + go func() { + // This is similar to invoking the + // containerd binary. + // See contrib/fuzz/oss_fuzz_build.sh + // for more info. + command.StartDaemonForFuzzing(args) + }() +} + +func fuzzContext() (context.Context, context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) + ctx = namespaces.WithNamespace(ctx, "fuzzing-namespace") + return ctx, cancel +} + +func FuzzContainerdImport(data []byte) int { + client, err := containerd.New(defaultAddress) + if err != nil { + return 0 + } + defer client.Close() + + f := fuzz.NewConsumer(data) + + noOfImports, err := f.GetInt() + if err != nil { + return 0 + } + maxImports := 20 + ctx, cancel := fuzzContext() + defer cancel() + for i := 0; i < noOfImports%maxImports; i++ { + tarBytes, err := f.GetBytes() + if err != nil { + return 0 + } + _, _ = client.Import(ctx, bytes.NewReader(tarBytes)) + } + return 1 +} diff --git a/contrib/fuzz/oss_fuzz_build.sh b/contrib/fuzz/oss_fuzz_build.sh index 61cc9235e..9aea05bbe 100755 --- a/contrib/fuzz/oss_fuzz_build.sh +++ b/contrib/fuzz/oss_fuzz_build.sh @@ -27,6 +27,30 @@ mv contrib/fuzz/docker_fuzzer.go remotes/docker/ mv contrib/fuzz/container_fuzzer.go integration/client/ +# Change path of socket since OSS-fuzz does not grant access to /run +sed -i 's/\/run\/containerd/\/tmp\/containerd/g' $SRC/containerd/defaults/defaults_unix.go + +# To build FuzzContainer2 we need to prepare a few things: +# We change the name of the cmd/containerd package +# so that we can import it. +# We furthermore add an exported function that is similar +# to cmd/containerd.main and call that instead of calling +# the containerd binary. +# +# In the fuzzer we import cmd/containerd as a low-maintenance +# way of initializing all the plugins. +# Make backup of cmd/containerd: +cp -r $SRC/containerd/cmd/containerd $SRC/cmd-containerd-backup +# Rename package: +find $SRC/containerd/cmd/containerd -type f -exec sed -i 's/package main/package mainfuzz/g' {} \; +# Add an exported function +sed -i -e '$afunc StartDaemonForFuzzing(arguments []string) {\n\tapp := App()\n\t_ = app.Run(arguments)\n}' $SRC/containerd/cmd/containerd/command/main.go +# Build fuzzer: +compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzContainerdImport fuzz_containerd_import +# Reinstante backup of cmd/containerd: +mv $SRC/cmd-containerd-backup $SRC/containerd/cmd/containerd + +# Compile more fuzzers compile_go_fuzzer github.com/containerd/containerd/remotes/docker FuzzFetcher fuzz_fetcher compile_go_fuzzer github.com/containerd/containerd/remotes/docker FuzzParseDockerRef fuzz_parse_docker_ref compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzFiltersParse fuzz_filters_parse @@ -38,7 +62,7 @@ compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzArchiveExpor compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzParseAuth fuzz_parse_auth compile_go_fuzzer github.com/containerd/containerd/contrib/fuzz FuzzParseProcPIDStatus fuzz_parse_proc_pid_status -# FuzzCreateContainer requires more setup than the fuzzers above. +# The below fuzzers require more setup than the fuzzers above. # We need the binaries from "make". wget -c https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_64.zip unzip protoc-3.11.4-linux-x86_64.zip -d /usr/local