Skip to content

Commit

Permalink
Intel PT minor fixes and improvements (AFLplusplus#2749)
Browse files Browse the repository at this point in the history
* Fix build target

Create target directory if doesn't exist

* Remove filter on speculatively exec blocks

since also committed blocks can have this flag

* Add current ip_filters getter

* Fix possibile infinite loop in trace decode

* Add comment about target_path
  • Loading branch information
Marcondiro authored Dec 6, 2024
0 parents commit 8999fe8
Show file tree
Hide file tree
Showing 19 changed files with 3,765 additions and 0 deletions.
55 changes: 55 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[package]
name = "libafl_libfuzzer"
version.workspace = true
description = "libFuzzer shim which uses LibAFL with common defaults"
repository = "https://github.com/AFLplusplus/LibAFL/"
readme = "../README.md"
license = "MIT OR Apache-2.0"
keywords = ["fuzzing", "testing", "security"]
edition = "2021"
categories = ["development-tools::testing"]

include = ["/src", "/Cargo.toml", "/build.rs", "/runtime"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[build-dependencies]
cc = "1.0.106"
rustversion = "1.0.17"
toml = { version = "0.8.19", features = ["preserve_order"] }

[features]
default = ["fork"]
document-features = ["dep:document-features"]

#! ## Feature Flags

## Enables the derive macros for the arbitrary dependency, transparently forwarded from libfuzzer-sys
arbitrary-derive = ["libfuzzer-sys/arbitrary-derive"]

## Enables forking in the fuzzer runtime for restarting managers for Unix systems (on by default)
fork = []

## Embeds the built libafl_libfuzzer_runtime library into the crate with include_bytes! for use
## in downstream cases like libafl_cc linking the runtime with:
## `-fsanitize=fuzzer-no-link -l:libafl_libfuzzer_runtime.a`
embed-runtime = []

## 🐇
rabbit = []

## For testing and publishing purposes only: enforce that the runtime uses versions rather than paths
libafl-libfuzzer-use-version = []

[dependencies]
libfuzzer-sys = { version = "0.4.7", default-features = false }
document-features = { workspace = true, optional = true }

[package.metadata.docs.rs]
features = ["document-features"]
all-features = true

rustdoc-args = ["--cfg", "docsrs"]

[lints]
workspace = true
163 changes: 163 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# libafl_libfuzzer

`libafl_libfuzzer` is a shim for [libFuzzer] which may be used in place of libFuzzer in most contexts.
It can be used both as a direct shim for existing libFuzzer-compatible targets which are simply linked with libFuzzer
(e.g., `clang -fsanitize=fuzzer`) and as a Rust crate for [`libfuzzer-sys`]-based harnesses.

## Background

`libafl_libfuzzer` was first developed as a shim in light of the [de-facto deprecation of libFuzzer].
Given the widespread use of libFuzzer and that LibAFL already supported most of the instrumentation used by libFuzzer,
we sought to develop a replacement which could directly replace it without much additional effort from the end user.
To do so, `libafl_libfuzzer` provides the same interface and uses the same instrumentation as libFuzzer so that
libFuzzer users can change over to a more modern LibAFL-based runtime without needing extensive changes to their
fuzzing environment or updating their harnesses.

## Usage

`libafl_libfuzzer` currently has known support for Rust, C, and C++ targets on Linux and macOS.
Windows is not currently supported, as we do not currently test or develop for Windows machines, but [we will happily
hear what issues you face and patch them as possible](https://github.com/AFLplusplus/LibAFL/issues/1563).

For both cases, you should install a recent **nightly** version of Rust via `rustup` and add the `llvm-tools` component
with `rustup component add llvm-tools`.

### Usage with Rust harnesses

To use `libafl_libfuzzer` on Rust harnesses which use `libfuzzer-sys`, all you need to do is change the following line
in your Cargo.toml:

```toml
libfuzzer-sys = { version = "...", features = ["your", "features", "here"] }
```

to

```toml
libfuzzer-sys = { version = "0.11.0", features = ["your", "features", "here"], package = "libafl_libfuzzer" }
```

To use the most up-to-date version (with experimental changes), use:

```toml
libfuzzer-sys = { git = "https://github.com/AFLplusplus/LibAFL.git", features = ["your", "features", "here"], package = "libafl_libfuzzer" }
```

As the repository generally offers the highest performance version of `libafl_libfuzzer`, we recommend the latter.
Remember to `cargo update` often if using the experimental changes, and please [submit an issue]
if you encounter problems while using the git branch!

For stability purposes, consider [specifying a commit](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choice-of-commit).

#### macOS

On macOS, you will need to add weak linking for some functions in a `build.rs` file:

```rust
fn main() {
for func in [
"_libafl_main",
"_LLVMFuzzerCustomMutator",
"_LLVMFuzzerCustomCrossOver",
] {
println!("cargo:rustc-link-arg=-Wl,-U,{func}");
}
}
```

#### Caveats

Like harnesses built with `libfuzzer-sys`, Rust targets which build other libraries (e.g. C/C++ FFI) may not
automatically apply instrumentation.
In addition to installing clang, you may also wish to set the following environmental variables:

```bash
CC=clang
CXX=clang++
CFLAGS='-fsanitize=fuzzer-no-link'
CXXFLAGS='-fsanitize=fuzzer-no-link'
```

### Usage as a standalone library (for C/C++/etc.)

The runtime for `libafl_libfuzzer` may be used standalone as a direct replacement for libFuzzer with other targets as
well.
To do so, [ensure a recent nightly version of Rust is installed](https://rustup.rs/), then enter the
[`libafl_libfuzzer_runtime`](../libafl_libfuzzer_runtime) folder and build the runtime with the following command:

```bash
./build.sh
```

The static library will be available at `libFuzzer.a` in the [`libafl_libfuzzer_runtime`](../libafl_libfuzzer_runtime)
directory.
If you encounter build failures without clear error outputs that help you resolve the issue, please [submit an issue].

This library may now be used in place of libFuzzer.
To do so, change your CFLAGS/CXXFLAGS from `-fsanitize=fuzzer` to:

```
-fsanitize=fuzzer-no-link -L/path/to/libafl_libfuzzer_runtime -lFuzzer
```

Alternatively, you may directly overwrite the system libFuzzer library and use `-fsanitize=fuzzer` as normal.
This changes per system, but on my machine is located at `/usr/lib64/clang/16/lib/linux/libclang_rt.fuzzer-x86_64.a`.

#### Caveats

This standalone library is _not_ compatible with Rust targets; you must instead use the crate-based dependency.
This is due to potential symbol conflict between your harness and the fuzzer runtime, which is resolved by additional
build steps provided in the `libafl_libfuzzer` crate itself.

## Flags

You can pass additional flags to the libFuzzer runtime in `cargo-fuzz` like so:

```bash
cargo fuzz run fuzz_target -- -extra_flag=1
```

When the runtime is used standalone, flags may be passed just like normal libFuzzer.

You will commonly need this for flags such as `-ignore_crashes=1` and `-timeout=5`. In addition
to partial support of libfuzzer flags, `libafl_libfuzzer` offers:

- `-dedup=n`, with `n` = 1 enabling deduplication of crashes by stacktrace.
- `-grimoire=n`, with `n` set to 0 or 1 disabling or enabling [grimoire] mutations, respectively.
- if not specified explicitly, `libafl_libfuzzer` will select based on whether existing inputs are UTF-8
- you should disable grimoire if your target is not string-like
- `-report=n`, with `n` = 1 causing `libafl_libfuzzer` to emit a report on the corpus content.
- `-skip_tracing=n`, with `n` = 1 causing `libafl_libfuzzer` to disable cmplog tracing.
- you should do this if your target performs many comparisons on memory sequences which are
not contained in the input
- `-tui=n`, with `n` = 1 enabling a graphical terminal interface.
- experimental; some users report inconsistent behaviour with tui enabled

### Supported flags from libfuzzer

- `-merge`
- `-minimize_crash`
- `-artifact_prefix`
- `-timeout`
- unlike libfuzzer, `libafl_libfuzzer` supports partial second timeouts (e.g. `-timeout=.5`)
- `-dict`
- `-fork` and `-jobs`
- in `libafl_libfuzzer`, these are synonymous
- `-ignore_crashes`, `-ignore_ooms`, and `-ignore_timeouts`
- note that setting `-tui=1` enables these flags by default, so you'll need to explicitly mention `-ignore_...=0` to
disable them
- `-rss_limit_mb` and `-malloc_limit_mb`
- `-ignore_remaining_args`
- `-shrink`
- `-runs`
- `-close_fd_mask`

[libFuzzer]: https://llvm.org/docs/LibFuzzer.html

[`libfuzzer-sys`]: https://docs.rs/libfuzzer-sys/

[de-facto deprecation of libFuzzer]: https://llvm.org/docs/LibFuzzer.html#status

[submit an issue]: https://github.com/AFLplusplus/LibAFL/issues/new/choose

[grimoire]: https://www.usenix.org/conference/usenixsecurity19/presentation/blazytko
Loading

0 comments on commit 8999fe8

Please sign in to comment.