blob: 962d41b80dcadcbbaf6d4cae6c64fd97d3cf8685 [file] [log] [blame]
// 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.
library fuchsia.fuzzer;
using zx;
/// Encapsulates transferring a fuzzer inputs over a socket, e.g. between a host and device via
/// overnet.
type Input = resource struct {
/// Socket that can be used to read the data.
socket zx.handle:SOCKET;
/// The total amount of data to be transferred.
size uint64;
};
/// See |Controller.Execute| and |Controller.Fuzz|.
type Result = flexible enum : uint32 {
/// No errors encountered.
NO_ERRORS = 1;
/// A single memory allocation by an instrumented remote process exceeded the configured limit.
BAD_MALLOC = 2;
/// An instrumented process raised an exception.
CRASH = 3;
/// A sanitizer runtime in an instrumented process detected an error.
DEATH = 4;
/// An instrumented process exited unexpectedly.
EXIT = 5;
/// A memory leak was detected in an instrumented process.
LEAK = 6;
/// An instrumented process's memory usage exceeded the configured limit.
OOM = 7;
/// A single run exceeded the configured limit.
TIMEOUT = 8;
};
/// Provides a |Controller| implementation.
///
/// This protocol is implemented by the fuzzer. This capability is *not* routed. Instead, the fuzzer
/// uses the channel provided by the fuzz-test-runner to send a client end of this interface to the
/// fuzz-registry via |Registry|.
///
/// The fuzz-registry will close the channel upon error, or upon its own exit. The fuzzer should
/// exit and not attempt to reconnect when on channel close.
protocol ControllerProvider {
/// Connects a client to the fuzzer.
///
/// Within the component fuzzing framework, the fuzz-manager forwards |Controller| connection
/// requests to the fuzz-registry, which uses clients of this interface provided by the fuzzers
/// themselves to perform the connection.
Connect(resource struct {
controller server_end:Controller;
}) -> ();
/// Interrupt any current workflow, closes the channel, and exits the fuzzing engine.
Stop();
};
/// Provides the management interface for fuzzing.
///
/// Within the component test framework, the fuzz_test_runner creates the underlying channel for
/// this protocol, passing one end to the fuzzer being started and the other to the fuzz_manager.
///
/// The channel is closed when the fuzzer is no longer needed, and on error. Clients should exit and
/// not attempt to reconnect.
protocol Controller {
/// See |Options|. Sets various execution and error detection parameters. This may be called
/// multiple times; only the most recently received options are used. If the |Options| parameter
/// omits one or more fields, those parameters are unchanged in the fuzzer. Until the initial
/// call to this method, the fuzzer should assume the default values for |Options|.
///
/// Returns ZX_OK if the options were set.
/// Returns ZX_ERR_BAD_STATE if a long-running call such as.Execute, Cleanse, Minimize, Fuzz, or
/// Merge is in progress.
Configure(struct {
options Options;
}) -> (struct {
result zx.status;
});
/// See |Options|. Gets the current values for the various execution and error detection
/// parameters.
GetOptions() -> (struct {
options Options;
});
/// Writes the provided |input| to either the "seed" or "live" |corpus|.
/// Returns an error if transferring the input fails; see |Input| for details.
AddToCorpus(resource struct {
corpus Corpus;
input Input;
}) -> (struct {
result zx.status;
});
/// Returns a connected |corpus_reader| for either the "seed" or "live" corpus.
ReadCorpus(resource struct {
corpus Corpus;
corpus_reader client_end:CorpusReader;
}) -> ();
/// Parses and loads an AFL-style dictionary. Invalid entries are logged and skipped.
/// See also:
/// https://github.com/mirrorer/afl/blob/master/dictionaries/README.dictionaries
///
/// Returns an error if transferring the input fails; see |Input| for details.
/// Returns ZX_ERR_INVALID_ARGS if parsing the dictionary fails.
WriteDictionary(resource struct {
dictionary Input;
}) -> (struct {
result zx.status;
});
/// Returns the current dictionary as an Input, which may be empty.
ReadDictionary() -> (resource struct {
dictionary Input;
});
/// See |Status|. Returns various fuzzing metrics, e.g. total coverage, speed, etc.
GetStatus() -> (struct {
status Status;
});
// Installs a |Monitor| to push status. To pull status instead, use |GetStatus|.
AddMonitor(resource struct {
monitor client_end:Monitor;
}) -> ();
/// Returns the result and the triggering input, if it exists, from the last fuzzing session.
GetResults() -> (resource struct {
result Result;
error_input Input;
});
/// Returns the result of running the target with a single |test_input|.
/// Returns an error if transferring the input fails; see |Input| for details.
Execute(resource struct {
test_input Input;
}) -> (struct {
result Result;
}) error zx.status;
/// Attempts to find the smallest input that produces the same error as the given |test_input|,
/// constrained by the configured |total_time| and/or |runs| options.
///
/// This is a long running call that continues executing after the method returns. Callers can
/// use |AddMonitor| to monitor the status of the call, and |GetResults| to retrieve the results
/// when it completes.
///
/// Returns ZX_ERR_BAD_STATE if another long-running call is in progress.
/// Returns ZX_ERR_INVALID_ARGS if the provided |test_input| does not cause an error.
/// Returns an error if taking an input fails; see |Input| for details.
Minimize(resource struct {
test_input Input;
}) -> (resource struct {
minimized Input;
}) error zx.status;
/// Attempts to replace bytes of the given |test_input| with "filler" bytes, e.g. \x00, \xFF,
/// without changing the error produced.
///
/// Returns ZX_ERR_INVALID_ARGS if the provided |test_input| does not cause an error.
/// Returns an error if taking an input fails; see |Input| for details.
Cleanse(resource struct {
test_input Input;
}) -> (resource struct {
cleansed Input;
}) error zx.status;
/// Runs the normal fuzzing feedback loop:
/// 1. Selects an input from the corpus.
/// 2. Mutates the input.
/// 3. Uses the |TargetAdapter| to execute the input.
/// 4. Checks feedback from the |InstrumentedProcesses|.
/// 5. If the input produced useful feedback, adds it to the corpus.
///
/// This loop continues until one of three conditions is met:
/// 1. The configured, non-zero number of |runs| has been reached.
/// 2. The configured, non-zero |duration| elapses.
/// 3. An error is detected, and returned.
///
/// This is a long running call that continues executing after the method returns. Callers can
/// use |AddMonitor| to monitor the status of the call, and |GetResults| to retrieve the results
/// when it completes.
///
/// Returns ZX_ERR_BAD_STATE if another long-running call is in progress.
Fuzz() -> (resource struct {
result Result;
error_input Input;
}) error zx.status;
/// Attempts to shrink the corpora. Inputs from the seed corpus will be preserved. All other
/// inputs will be sorted by amount of feedback produced and input size, and only those inputs
/// that add new feedback not seen earlier in the sequence will be kept.
///
/// This is a long running call that continues executing after the method returns. Callers can
/// use |AddMonitor| to monitor the status of the call, and |GetCorpusReader| to retrieve the
/// results when it completes.
///
/// Returns ZX_ERR_BAD_STATE if another long-running call is in progress.
/// Returns ZX_ERR_INVALID_ARGS if an input in the seed corpus causes an error. Skips inputs in
/// the live corpus that cause errors.
Merge() -> (struct {
result zx.status;
});
};