blob: ac194b873855c891e744cf35c21451bf4f8a0207 [file] [log] [blame] [edit]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_SYS_FUZZING_COMMON_RUNNER_H_
#define SRC_SYS_FUZZING_COMMON_RUNNER_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/function.h>
#include <lib/sync/completion.h>
#include <atomic>
#include <memory>
#include <thread>
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/synchronization/thread_annotations.h"
#include "src/sys/fuzzing/common/input.h"
#include "src/sys/fuzzing/common/options.h"
namespace fuzzing {
using ::fuchsia::fuzzer::MonitorPtr;
using ::fuchsia::fuzzer::Result;
using ::fuchsia::fuzzer::Status;
using ::fuchsia::fuzzer::TargetAdapter;
using ::fuchsia::fuzzer::UpdateReason;
using CorpusType = ::fuchsia::fuzzer::Corpus;
// This base class encapsulates the logic of performing a sequence of fuzzing runs. In
// particular, it defines virtual methods for performing the fuzzing workflows asynchronously, and
// invokes those methods on a dedicated worker thread to perform them without blocking the
// controller's FIDL dispatcher thread.
class Runner {
public:
virtual ~Runner();
// Accessors.
Result result() const { return result_; }
Input result_input() const { return result_input_.Duplicate(); }
// Lets this objects add defaults to unspecified options.
virtual void AddDefaults(Options* options) = 0;
// Add an input to the specified corpus. Returns ZX_ERR_INVALID_ARGS if |corpus_type| is
// unrecognized.
virtual zx_status_t AddToCorpus(CorpusType corpus_type, Input input) = 0;
// Returns a copy of the input at the given |offset| in the corpus of the given |corpus_type|,
// or an emtpy input if |offset| is invalid.
virtual Input ReadFromCorpus(CorpusType corpus_type, size_t offset) = 0;
// Parses the given |input| as an AFL-style dictionary. For format details, see
// https://lcamtuf.coredump.cx/afl/technical_details.txt. Returns ZX_ERR_INVALID_ARGS if parsing
// fails.
virtual zx_status_t ParseDictionary(const Input& input) = 0;
// Returns the current dictionary serialized into an |Input|.
virtual Input GetDictionaryAsInput() const = 0;
// Fuzzing workflows.
zx_status_t Configure(const std::shared_ptr<Options>& options);
void Execute(Input input, fit::function<void(zx_status_t)> callback) FXL_LOCKS_EXCLUDED(mutex_);
void Minimize(Input input, fit::function<void(zx_status_t)> callback) FXL_LOCKS_EXCLUDED(mutex_);
void Cleanse(Input input, fit::function<void(zx_status_t)> callback) FXL_LOCKS_EXCLUDED(mutex_);
void Fuzz(fit::function<void(zx_status_t)> callback) FXL_LOCKS_EXCLUDED(mutex_);
void Merge(fit::function<void(zx_status_t)> callback) FXL_LOCKS_EXCLUDED(mutex_);
// Adds a subscriber for status updates.
void AddMonitor(MonitorPtr monitor) FXL_LOCKS_EXCLUDED(mutex_);
// Creates a |Status| object representing all attached processes.
Status CollectStatus() FXL_LOCKS_EXCLUDED(mutex_);
protected:
Runner();
virtual void set_result(Result result) { result_ = result; }
virtual void set_result_input(const Input& input) { result_input_ = input.Duplicate(); }
// Fuzzing workflow implementations.
virtual void ConfigureImpl(const std::shared_ptr<Options>& options) = 0;
virtual zx_status_t SyncExecute(const Input& input) = 0;
virtual zx_status_t SyncMinimize(const Input& input) = 0;
virtual zx_status_t SyncCleanse(const Input& input) = 0;
virtual zx_status_t SyncFuzz() = 0;
virtual zx_status_t SyncMerge() = 0;
// Creates a |Status| object representing all attached processes.
virtual Status CollectStatusLocked() = 0;
// Resets the error state for subsequent actions.
virtual void ClearErrors();
// Collects the current status, labels it with the given |reason|, and sends it all attached
//|Monitor|s.
void UpdateMonitors(UpdateReason reason) FXL_LOCKS_EXCLUDED(mutex_);
private:
// Schedule a workflow to be performed by the worker thread.
void Pend(uint8_t action, Input input, fit::function<void(zx_status_t)> callback)
FXL_LOCKS_EXCLUDED(mutex_);
// The worker thread body.
void Worker() FXL_LOCKS_EXCLUDED(mutex_);
std::mutex mutex_;
// Worker variables.
std::thread worker_;
sync_completion_t worker_sync_;
bool idle_ FXL_GUARDED_BY(mutex_) = false;
uint8_t action_ FXL_GUARDED_BY(mutex_);
Input input_ FXL_GUARDED_BY(mutex_);
fit::function<void(zx_status_t)> callback_ FXL_GUARDED_BY(mutex_);
// Result variables.
Result result_ = Result::NO_ERRORS;
Input result_input_;
std::vector<MonitorPtr> monitors_ FXL_GUARDED_BY(mutex_);
FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(Runner);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_COMMON_RUNNER_H_