| // 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; |
| }; |
| |
| /// Indicates the result of a long-running fuzzing workflow. |
| /// |
| /// Fuzzers have several "long-running" workflows; that is, the fuzzer may perform actions for an |
| /// indefinite period of time. Fuzzing itself is the most notable example, as the fuzzing engine may |
| /// continuously generate new inputs until an error is found. This workflow is represented by the |
| /// `Fuzz` method below. Other long-running workflows include `TryOne`, `Cleanse`, `Minimize` and |
| /// `Merge`. |
| 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; |
| |
| /// The associated input was produced by finding the shortest input that produces the same error |
| /// as an original input. See `Minimize`. |
| MINIMIZED = 9; |
| |
| /// The associated input was produced by replacing bytes in an original input with PII-free |
| /// values while preserving the error produced. See `Cleanse`. |
| CLEANSED = 10; |
| |
| /// The fuzzer corpus has been compacted to only include the shortest inputs that preserve |
| /// overall coverage. This workflow does not have an associated input. See `Merge`. |
| MERGED = 11; |
| }; |
| |
| /// 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; |
| }); |
| }; |
| |
| /// Marker indicating the last message in a diagnostic output stream. |
| /// |
| /// In addition to the FIDL interactions described above, a client of `fuchsia.fuzzer.Controller` |
| /// typically also receives the standard output, standard error, and system log from the fuzzer's |
| /// realm, e.g. via `fuchsia.test_manager.RunBuilder` and its controllers and events. These streams |
| /// have no guaranteed order with respect to FIDL responses. This is a particular problem for |
| /// the long-running workflows. As a result, the streams need to include an "in-band" signal that |
| /// the diagnostics for a particular workflow are complete. Clients processing the output may use |
| /// this marker to synchronize them and the FIDL response for a workflow. |
| /// |
| /// The string is intentionally somewhat long to mitigate the likelihood of it being emitted by the |
| /// code under test. |
| /// |
| const DONE_MARKER string = "DONE: A long-running `fuchsia.fuzzer.Controller` workflow is complete."; |