Expand description
Detect persistent writable state between fuzzer iterations.
Rust bindings for the global-state-detector C library. Operates
on writable, non-executable ELF PT_LOAD segments (.data / .bss)
of the main binary and every loaded shared object, filtering out
libc / ld-linux / libpthread / libstdc++ / vDSO noise.
§Usage
Call init once after any one-time target initialization is done.
Then, on each fuzzer iteration, rebaseline just before invoking
the target and check just after. That pattern attributes drift
to the target rather than to the fuzzer’s own bookkeeping between
callbacks.
§Required linker flags for the final binary
Cargo does not propagate rustc-link-arg from rlib dependencies, so
consumers must arrange for the linker to receive -rdynamic and
-Wl,-z,now themselves. The simplest way is a .cargo/config.toml
in the consuming project (or its fuzz/ subdirectory):
[target.'cfg(target_os = "linux")']
rustflags = ["-C", "link-arg=-rdynamic", "-C", "link-arg=-Wl,-z,now"]Without -rdynamic, symbol names in the main executable are not
resolvable via dladdr and reports show ?+0x... instead of real
symbols. Without -Wl,-z,now, lazy PLT/GOT binding produces noise
on the first iteration.
§Rust-specific caveats
staticandstatic mutlive in.data/.bss— fully covered.AtomicU*,Mutex<T>(the lock word),RwLock— covered.OnceCell,OnceLock,LazyLock,lazy_static!— only the pointer / discriminant in.bssis visible. The actual heap- allocated payload is NOT tracked. You will see “this static was first-used in this iteration” but not what value it took.thread_local!lives in TLS, not.data/.bss— not tracked here. TLS is per-thread anyway, less of a fuzzing concern.- Symbols come out Rust-mangled (
_ZN8.../_R...). Pipe stderr throughrustfiltto demangle: ./fuzzer 2>&1 | rustfilt (cargo install rustfilt)
§Thread safety
The underlying C implementation is not thread-safe. Use it from a single-threaded harness, or add external synchronization.
Functions§
- check
- Diff current memory against the last snapshot.
- init
- Snapshot all writable
PT_LOADsegments of the main binary and every currently loaded shared object. - rebaseline
- Force a full re-snapshot without reporting any diffs.