Documentation ¶
Index ¶
- Constants
- Variables
- func CreateProcess(name string, args ...string) error
- func CreateProcessForeground(name string, args ...string) error
- func NewCommand(name string, args ...string) *exec.Cmd
- type APICommand
- type BaseBuild
- type BaseInstance
- func (i *BaseInstance) Close()
- func (i *BaseInstance) Get(fuzzerName, targetSrc, hostDst string) error
- func (i *BaseInstance) GetLogs(out io.Writer) error
- func (i *BaseInstance) Handle() (Handle, error)
- func (i *BaseInstance) ListFuzzers() []string
- func (i *BaseInstance) PrepareFuzzer(name string) error
- func (i *BaseInstance) Put(fuzzerName, hostSrc, targetDst string) error
- func (i *BaseInstance) RunFuzzer(out io.Writer, name, hostArtifactDir string, args ...string) error
- func (i *BaseInstance) Start() error
- func (i *BaseInstance) Stop() error
- type Build
- type Connector
- type Fuzzer
- type Handle
- type HandleData
- type Instance
- type InstanceCmd
- type InstanceCmdError
- type Launcher
- type QemuLauncher
- type SSHConnector
- func (c *SSHConnector) Close()
- func (c *SSHConnector) Command(name string, args ...string) InstanceCmd
- func (c *SSHConnector) Connect() error
- func (c *SSHConnector) Get(targetSrc string, hostDst string) error
- func (c *SSHConnector) GetSysLog(pid int) (string, error)
- func (c *SSHConnector) Put(hostSrc string, targetDst string) error
- type SSHInstanceCmd
- func (c *SSHInstanceCmd) Kill() error
- func (c *SSHInstanceCmd) Output() ([]byte, error)
- func (c *SSHInstanceCmd) Run() error
- func (c *SSHInstanceCmd) SetTimeout(duration time.Duration)
- func (c *SSHInstanceCmd) Start() error
- func (c *SSHInstanceCmd) StdinPipe() (io.WriteCloser, error)
- func (c *SSHInstanceCmd) StdoutPipe() (io.ReadCloser, error)
- func (c *SSHInstanceCmd) Wait() error
Constants ¶
const ( VersionMajor = 0 VersionMinor = 1 VersionPatch = 0 )
API version
const ( StartInstance = "start_instance" StopInstance = "stop_instance" ListFuzzers = "list_fuzzers" PrepareFuzzer = "prepare_fuzzer" GetLogs = "get_logs" RunFuzzer = "run_fuzzer" GetData = "get_data" PutData = "put_data" Version = "version" )
Available subcommand names
const ( FakeQemuNormal = "qemu-system-x86_64" FakeQemuFailing = "failing-qemu" FakeQemuSlow = "slow-qemu" )
Variables ¶
var Archs = map[string]struct { Binary string Kernel string }{ "x64": {"qemu-system-x86_64", "multiboot.bin"}, "arm64": {"qemu-system-aarch64", "qemu-boot-shim.bin"}, }
var ExecCommand = exec.Command
ExecCommand is the function used by CreateProcess to create Cmd objects. Test code can replace the default to mock process creation.
var NewBuild = NewBuildFromEnvironment
This is stubbed out to allow for test code to replace it
var Platforms = map[string]string{
"linux": "linux",
"darwin": "mac",
}
Functions ¶
func CreateProcess ¶
Run a command to completion
func CreateProcessForeground ¶
CreateProcessForeground is like CreateProcess but passes through any command output
Types ¶
type APICommand ¶
type APICommand struct {
// contains filtered or unexported fields
}
An APICommand is the structured result of parsing the command-line args
func ParseArgs ¶
func ParseArgs(args []string) (*APICommand, error)
ParseArgs converts command-line args into an API-command
type BaseBuild ¶
BaseBuild is a simple implementation of the Build interface
func (*BaseBuild) ListFuzzers ¶
ListFuzzers lists the names of fuzzers present in the build TODO(fxbug.dev/45108): handle variant stripping
func (*BaseBuild) LoadFuzzers ¶
LoadFuzzers reads and parses fuzzers.json to populate the build's map of Fuzzers. Unless an error is returned, any previously loaded fuzzers will be discarded.
func (*BaseBuild) Path ¶
Path returns the absolute paths to the list of files indicated by keys. This allows callers to abstract away the detail of where specific file resources are.
type BaseInstance ¶
type BaseInstance struct { Build Build Connector Connector Launcher Launcher // contains filtered or unexported fields }
BaseInstance groups the core subobjects, to which most work will be delegated
func (*BaseInstance) Close ¶
func (i *BaseInstance) Close()
Close releases the Instance, but doesn't Stop it
func (*BaseInstance) Get ¶
func (i *BaseInstance) Get(fuzzerName, targetSrc, hostDst string) error
Get copies files from a fuzzer namespace on the Instance to the host
func (*BaseInstance) GetLogs ¶
func (i *BaseInstance) GetLogs(out io.Writer) error
GetLogs writes any system logs for an instance to `out`
func (*BaseInstance) Handle ¶
func (i *BaseInstance) Handle() (Handle, error)
Handle returns a Handle representing the Instance
func (*BaseInstance) ListFuzzers ¶
func (i *BaseInstance) ListFuzzers() []string
ListFuzzers lists fuzzers available on the Instance
func (*BaseInstance) PrepareFuzzer ¶
func (i *BaseInstance) PrepareFuzzer(name string) error
PrepareFuzzer ensures the named fuzzer is ready to be used on the Instance. This must be called before running the fuzzer or exchanging any data with the fuzzer. If called for a fuzzer that has already been previously prepared, it will reset the state of that fuzzer: clearing data directories, etc.
This method is explicitly separated from RunFuzzer and others to ensure that any caller timeouts being enforced on fuzzer command execution are not affected by unrelated setup delays such as package fetching over the network.
func (*BaseInstance) Put ¶
func (i *BaseInstance) Put(fuzzerName, hostSrc, targetDst string) error
Put copies files from the host to a fuzzer namespace on the Instance
func (*BaseInstance) RunFuzzer ¶
RunFuzzer runs the named fuzzer on the Instance. If `hostArtifactDir` is specified and the run generated any output artifacts, they will be copied to that directory. `args` is an optional list of arguments in the form `-key=value` that will be passed to libFuzzer.
func (*BaseInstance) Start ¶
func (i *BaseInstance) Start() error
Start boots up the instance and waits for connectivity to be established
If Start succeeds, it is up to the caller to clean up by calling Stop later. However, if it fails, any resources will have been automatically released.
type Build ¶
type Build interface { // Ensures all the needed resources are present and fetches any that are // missing. Multiple calls to Prepare should be idempotent for the same // Build. Prepare() error // Returns a fuzzer specified by a `package/binary` name, or an error if it // isn't found. Fuzzer(name string) (*Fuzzer, error) // Returns the absolute host paths for each key. Each key corresponds to a // specific resource provided by the Build. This abstraction allows for // different build types to have different structures. Path(keys ...string) ([]string, error) // Reads input from `in`, symbolizes it, and writes it back to `out`. // Returns on error, or when `in` has no more data to read. Processing // will be streamed, line-by-line. // TODO(fxbug.dev/47482): does this belong elsewhere? Symbolize(in io.Reader, out io.Writer) error // Returns a list of the names of the fuzzers that are available to run ListFuzzers() []string }
A Build represents a Fuchsia build, consisting of all the resources needed to run a fuzzer on an instance (e.g. a Fuchsia image, fuzzer packages and metadata, binary symbols, support utilities, etc.).
func NewBuildFromEnvironment ¶
Attempt to auto-detect the correct Build type
func NewClusterFuzzLegacyBuild ¶
NewClusterFuzzLegacyBuild will create a BaseBuild with path layouts corresponding to the legacy build bundles used by ClusterFuzz's original Python integration. Note that these build bundles only support x64.
func NewLocalFuchsiaBuild ¶
NewLocalFuchsiaBuild will create a BaseBuild with path layouts corresponding to a local Fuchsia checkout
type Connector ¶
type Connector interface { // Connect establishes all necessary connections to the instance. It does // not need to be explicitly called, because the other Connector methods will // automatically connect if necessary, but may be called during initializiation. // It the connector is already connected, an error will be returned. Connect() error // Close closes any open connections to the instance. It is the client's // responsibility to call Close() when cleaning up the Connector. Close() // Returns an InstanceCmd representing the command to be run on the instance. Only one // command should be active at a time. // TODO(fxbug.dev/47479): In some cases, we should be able to relax the above restriction Command(name string, args ...string) InstanceCmd // Copies targetSrc (may include globs) to hostDst, which is always assumed // to be a directory. Directories are copied recursively. Get(targetSrc, hostDst string) error // Copies hostSrc (may include globs) to targetDst, which is always assumed // to be a directory. Directories are copied recursively. Put(hostSrc, targetDst string) error // Retrieves a syslog from the instance, filtered to the given process ID GetSysLog(pid int) (string, error) }
A Connector is used to communicate with an instance
type Fuzzer ¶
type Fuzzer struct { // Name is `package/binary` Name string // contains filtered or unexported fields }
A Fuzzer represents a fuzzer present on an instance.
func (*Fuzzer) AbsPath ¶
AbsPath returns the absolute target path for a given relative path in a fuzzer package. The path may differ depending on whether it is identified as a resource, data, or neither.
func (*Fuzzer) Parse ¶
Parse command line arguments for the fuzzer. For '-key=val' style options, the last 'val' for a given 'key' is used.
func (*Fuzzer) Prepare ¶
PrepareFuzzer ensures the named fuzzer is ready to be used on the Instance. This must be called before running the fuzzer or exchanging any data with the fuzzer.
type Handle ¶
type Handle string
func LoadHandleFromString ¶
LoadHandleFromString recreates a previously-created Handle from its string representation as returned by Serialize()
func NewHandle ¶
NewHandle allocates a new handle for use. It will persist until explicitly Released.
func NewHandleWithData ¶
func NewHandleWithData(initialData HandleData) (Handle, error)
NewHandleWithData is a convenience function for populating a new Handle at the same time as creating it.
func (Handle) GetData ¶
func (h Handle) GetData() (*HandleData, error)
GetData will load and return data from the Handle, as previously stored by SetData.
func (Handle) Release ¶
func (h Handle) Release()
Release removes any resources used by the Handle. After calling Release, the handle will become invalid and cannot be further used.
func (Handle) SetData ¶
func (h Handle) SetData(data HandleData) error
SetData stores all exported fields of the given data into the Handle, so they can later be retrieved with GetData. Any existing data in the Handle will be overwritten.
type HandleData ¶
type HandleData struct {
// contains filtered or unexported fields
}
HandleData represents the top-level structure of the data stored within the Handle.
type Instance ¶
type Instance interface { Start() error Stop() error ListFuzzers() []string Get(fuzzerName, targetSrc, hostDst string) error Put(fuzzerName, hostSrc, targetDst string) error RunFuzzer(out io.Writer, name, hostArtifactDir string, args ...string) error GetLogs(out io.Writer) error PrepareFuzzer(name string) error Handle() (Handle, error) Close() }
An Instance is a specific combination of build, connector, and launcher, representable by a handle. Most methods of this interface map directly to the ClusterFuchsia API.
type InstanceCmd ¶
type InstanceCmd interface { // Output runs the command and returns its combined output. Output() ([]byte, error) // Runs the specified command and waits for it to complete. // // The returned error is nil if the command runs, has no problems copying // input and output, and exits with a zero exit status. Run() error // Start starts the specified command but does not wait for it to complete. Start() error // StdinPipe returns a pipe that will be connected to the command's input // when the command starts. The pipe will be closed automatically after // Wait sees the command exit. A caller need only call Close to force the // pipe to close sooner. For example, if the command being run will not // exit until the input is closed, the caller must close the pipe. StdinPipe() (io.WriteCloser, error) // StdoutPipe returns a pipe that will be connected to the command's output // when the command starts. // // Wait will close the pipe after seeing the command exit, so most callers // need not close the pipe themselves; however, an implication is that it // is incorrect to call Wait before all reads from the pipe have completed. // For the same reason, it is incorrect to call Run when using StdoutPipe. StdoutPipe() (io.ReadCloser, error) // Wait waits for the command to exit and waits for any copying // to input or from output to complete. // // The command must have been started by Start. // // The returned error is nil if the command runs, has no problems // copying input and output, and exits with a zero exit status // before any timeout set with SetTimeout is triggered. // // Wait releases any resources associated with the InstanceCmd. Wait() error // SetTimeout sets a timeout that will be used for all blocking // methods. If a method takes longer than the timeout duration to // complete, it will return early with an error. If not set, or // set to 0, methods will block forever. SetTimeout(duration time.Duration) // Kill forcefully terminates the remote command Kill() error }
An InstanceCmd represents a remote command to be run on an Instance This interface is similar to that of os.exec.Cmd
type InstanceCmdError ¶
InstanceCmdError includes extra information when commands fail
func (*InstanceCmdError) Error ¶
func (e *InstanceCmdError) Error() string
type Launcher ¶
type Launcher interface { // Do any preparation necessary before starting. This is idempotent, and // does not need to be explicitly called by the client, as it will be // automatically called by Start as necessary. Prepare() error // Starts the instance, returning a Connector that can be used to communicate with it Start() (Connector, error) // Returns true iff the instance is running. IsRunning() (bool, error) // Stops the instance. This is allowed to take up to 3 seconds to return. Kill() error // Dump any available system or debug logs to `out` GetLogs(out io.Writer) error }
A Launcher manages the lifecycle of an instance; e.g. starting and stopping
type QemuLauncher ¶
A QemuLauncher starts Fuchsia on QEMU
func NewQemuLauncher ¶
func NewQemuLauncher(build Build) *QemuLauncher
NewQemuLauncher constructs a new QemuLauncher
func (*QemuLauncher) GetLogs ¶
func (q *QemuLauncher) GetLogs(out io.Writer) error
GetLogs writes any system logs from QEMU to `out`
func (*QemuLauncher) IsRunning ¶
func (q *QemuLauncher) IsRunning() (bool, error)
IsRunning checks if the qemu process is alive
func (*QemuLauncher) Kill ¶
func (q *QemuLauncher) Kill() error
Kill tells the QEMU process to terminate, and cleans up the TmpDir
func (*QemuLauncher) Prepare ¶
func (q *QemuLauncher) Prepare() (returnErr error)
Prepare files that are needed by QEMU, if they haven't already been prepared.
If Prepare succeeds, it is up to the caller to clean up by calling Kill later. However, if it fails, any resources will have been automatically released.
func (*QemuLauncher) Start ¶
func (q *QemuLauncher) Start() (conn Connector, returnErr error)
Start launches QEMU and waits for it to get through the basic boot sequence. Note that networking will not necessarily be fully up by the time Start() returns
If Start succeeds, it is up to the caller to clean up by calling Kill later. However, if it fails, any resources will have been automatically released.
type SSHConnector ¶
type SSHConnector struct { // Host can be any IP or hostname as accepted by net.Dial Host string Port int // Key is a path to the SSH private key that should be used for // authentication Key string // contains filtered or unexported fields }
An SSHConnector is a Connector that uses SSH/SFTP for transport Note: exported fields will be serialized to the handle
func (*SSHConnector) Command ¶
func (c *SSHConnector) Command(name string, args ...string) InstanceCmd
Command returns an InstanceCmd that can be used to given command over SSH
func (*SSHConnector) Get ¶
func (c *SSHConnector) Get(targetSrc string, hostDst string) error
Get fetches files over SFTP
type SSHInstanceCmd ¶
type SSHInstanceCmd struct {
// contains filtered or unexported fields
}
A SSHInstanceCmd represents a command to be run over SSH
func (*SSHInstanceCmd) Kill ¶
func (c *SSHInstanceCmd) Kill() error
Kill sends a KILL signal to the remote process
func (*SSHInstanceCmd) Output ¶
func (c *SSHInstanceCmd) Output() ([]byte, error)
Output executes the command and returns its output
func (*SSHInstanceCmd) Run ¶
func (c *SSHInstanceCmd) Run() error
Run runs the command to completion
func (*SSHInstanceCmd) SetTimeout ¶
func (c *SSHInstanceCmd) SetTimeout(duration time.Duration)
SetTimeout sets the global timeout
func (*SSHInstanceCmd) Start ¶
func (c *SSHInstanceCmd) Start() error
Start the command, but don't wait for it to complete
func (*SSHInstanceCmd) StdinPipe ¶
func (c *SSHInstanceCmd) StdinPipe() (io.WriteCloser, error)
StdinPipe returns a pipe connected to the command's input
func (*SSHInstanceCmd) StdoutPipe ¶
func (c *SSHInstanceCmd) StdoutPipe() (io.ReadCloser, error)
StdoutPipe returns a pipe connected to the command's output TODO(fxbug.dev/45424): this currently includes stderr in addition to stdout TODO(fxbug.dev/45424): use ssh.Session's implementation of pipe stuff, etc
func (*SSHInstanceCmd) Wait ¶
func (c *SSHInstanceCmd) Wait() error
Wait for the remote command to complete