Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions smite-nyx-sys/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,72 @@
//! Low level FFI bindings to the Nyx agent for snapshot based fuzzing
//!
//! [Nyx](https://nyx-fuzz.com/) is a hypervisor based snapshot fuzzer that
//! runs the target inside a modified QEMU VM. After an initial setup phase
//! the VM state is snapshotted and each fuzz iteration restores the snapshot,
//! injects a new input and collects coverage. And all this without restarting the
//! target process.
Comment on lines +6 to +7
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! injects a new input and collects coverage. And all this without restarting the
//! target process.
//! injects a new input and collects coverage without restarting the target
//! process.

//!
//! This crate compiles the C agent (`nyx-agent.c`) via `build.rs` and exposes
//! its functions to Rust. The bundled build defines `NO_PT_NYX` so the agent
//! communicates with the Nyx hypervisor through the x86 port-I/O hypercall path
//! defined in `nyx.h`.

use std::os::raw::{c_char, c_uchar};

// Exposed nyx agent functions.
//
// See docs in `smite-nyx-sys/src/nyx-agent.c`
unsafe extern "C" {
/// Initializes the Nyx agent and returns the maximum fuzz input size
/// (in bytes) supported by the host.
Comment on lines +20 to +21
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Initializes the Nyx agent and returns the maximum fuzz input size
/// (in bytes) supported by the host.
/// Initializes the Nyx agent and returns the maximum fuzz input size
/// (in bytes) supported by the host. Also sets `__AFL_SHM_ID` to the
/// allocated shared memory ID and sets `AFL_MAP_SIZE` to the size of
/// the shared memory region.

pub fn nyx_init() -> usize;

/// Dumps the contents of `data` to a file on the host filesystem
/// named by the first `file_name_len` bytes of `file_name`.
///
/// Useful for exporting crash logs, coverage data or other artifacts
/// from the guest VM to the host for post-processing.
pub fn nyx_dump_file_to_host(
file_name: *const c_char,
file_name_len: usize,
data: *const c_uchar,
len: usize,
);

/// Retrieves the next fuzz input from the Nyx hypervisor.
///
/// On first entry this maps the payload buffer, resets coverage
/// and takes the VM snapshot via `HYPERCALL_KAFL_USER_FAST_ACQUIRE`.
/// Later iterations resume after that snapshot point and copy the current
/// payload into `data`.
///
/// `data` must be large enough for the full payload; the C agent does not
/// clamp the copy to `max_size`. Pass the size returned by [`nyx_init`].
Comment on lines +43 to +44
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think it does? max_size determines the size of the payload buffer, which will naturally be the largest input that can ever be returned in data.

Suggested change
/// `data` must be large enough for the full payload; the C agent does not
/// clamp the copy to `max_size`. Pass the size returned by [`nyx_init`].
/// `max_size` is the maximum number of bytes that can be written to `data`.

///
/// Returns the actual fuzz input size.
pub fn nyx_get_fuzz_input(data: *const c_uchar, max_size: usize) -> usize;

/// Skips the current test case and resets the coverage bitmap and restores
/// the VM to the snapshot state.
/// After this call, execution resumes from the snapshot point inside
/// [`nyx_get_fuzz_input`].
Comment on lines +49 to +52
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Skips the current test case and resets the coverage bitmap and restores
/// the VM to the snapshot state.
/// After this call, execution resumes from the snapshot point inside
/// [`nyx_get_fuzz_input`].
/// Skips the current test case, resets the coverage bitmap, and restores the
/// VM to the snapshot state. After this call, execution resumes from the
/// snapshot point inside [`nyx_get_fuzz_input`].

pub fn nyx_skip();

/// Signals the end of a test case and restores the VM to the snapshot
/// state.
/// After this call the execution resumes from the snapshot point inside
/// [`nyx_get_fuzz_input`].
Comment on lines +56 to +58
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// state.
/// After this call the execution resumes from the snapshot point inside
/// [`nyx_get_fuzz_input`].
/// state. After this call the execution resumes from the snapshot point
/// inside [`nyx_get_fuzz_input`].

pub fn nyx_release();

/// Reports a crash to the Nyx hypervisor with the given diagnostic
/// message.
///
/// `message` must be a valid, null terminated C string. The hypervisor
/// records this as a crash input and the message is included in the
/// crash report.
pub fn nyx_fail(message: *const c_char);

/// Prints a message to the Nyx host console via `hprintf`.
/// Messages longer than the hypervisor buffer limit are sent in chunks.
pub fn nyx_println(message: *const c_char, size: usize);
}
Loading