Skip to content

libafl_libfuzzer: rename all symbols #1565

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ jobs:
with:
profile: minimal
toolchain: stable
components: llvm-tools
- name: Remove existing clang and LLVM
run: sudo apt purge llvm* clang*
- name: Install and cache deps
Expand Down
3 changes: 3 additions & 0 deletions libafl_libfuzzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ introspection = []
## `-fsanitize=fuzzer-no-link -l:libafl_libfuzzer_runtime.a`
embed-runtime = []

## 🐇
rabbit = []

[dependencies]
libfuzzer-sys = { version = "0.4.7", default-features = false }
document-features = { version = "0.2" }
Expand Down
161 changes: 148 additions & 13 deletions libafl_libfuzzer/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
use std::{path::PathBuf, process::Command};

use std::{
fs::File,
io::{BufRead, BufReader, BufWriter, Write},
path::PathBuf,
process::{Command, Stdio},
};

#[cfg(feature = "rabbit")]
const NAMESPACE: &str = "🐇";
#[cfg(not(feature = "rabbit"))]
const NAMESPACE: &str = "__libafl";
const NAMESPACE_LEN: usize = NAMESPACE.as_bytes().len();

#[allow(clippy::too_many_lines)]
fn main() {
if cfg!(any(feature = "cargo-clippy", docsrs)) {
return; // skip when clippy or docs is running
Expand Down Expand Up @@ -69,20 +81,143 @@ fn main() {
let mut lib_path = custom_lib_dir.join(std::env::var_os("TARGET").unwrap());
lib_path.push("release");

#[cfg(all(feature = "embed-runtime", target_family = "unix"))]
{
// NOTE: lib, .a are added always on unix-like systems as described in:
// https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b
if cfg!(target_family = "unix") {
use std::path::Path;

lib_path.push("libafl_libfuzzer_runtime.a");
let target_libdir = Command::new("rustc")
.args(["--print", "target-libdir"])
.output()
.expect("Couldn't find rustc's target-libdir");
let target_libdir = String::from_utf8(target_libdir.stdout).unwrap();
let target_libdir = Path::new(target_libdir.trim());

let rust_lld = target_libdir.join("../bin/rust-lld");
let rust_ar = target_libdir.join("../bin/llvm-ar"); // NOTE: depends on llvm-tools
let rust_objcopy = target_libdir.join("../bin/llvm-objcopy"); // NOTE: depends on llvm-tools
let nm = "nm"; // NOTE: we use system nm here because llvm-nm doesn't respect the encoding?

let redefined_symbols = custom_lib_dir.join("redefs.txt");

let objfile_orig = custom_lib_dir.join("libFuzzer.o");
let objfile_dest = custom_lib_dir.join("libFuzzer-mimalloc.o");

let mut command = Command::new(rust_lld);
command
.args(["-flavor", "gnu"])
.arg("-r")
Copy link
Member

Choose a reason for hiding this comment

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

partial linking works with GNU ld too in case

.arg("--whole-archive")
.arg(lib_path)
.args(["-o", objfile_orig.to_str().expect("Invalid path characters present in your current directory prevent us from linking to the runtime")]);

assert!(
!command.status().map(|s| !s.success()).unwrap_or(true),
"Couldn't link runtime crate! Do you have the llvm-tools component installed?"
);

let mut child = Command::new(nm)
.arg(&objfile_orig)
.stdout(Stdio::piped())
.spawn()
.unwrap();

let mut redefinitions_file = BufWriter::new(File::create(&redefined_symbols).unwrap());

let replacement = format!("_ZN{NAMESPACE_LEN}{NAMESPACE}");

// redefine all the rust-mangled symbols we can
// TODO this will break when v0 mangling is stabilised
for line in BufReader::new(child.stdout.take().unwrap()).lines() {
Copy link
Member

Choose a reason for hiding this comment

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

can't we just avoid to export symbols when generating the runtime lib? like partial linking and then remove all symbols

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We want to retain these symbols for both debugging purposes and because we need to retain certain unmangled symbols (e.g. LLVMFuzzerRuntime, LLVMFuzzerMutate, etc.)

let line = line.unwrap();
let (_, symbol) = line.rsplit_once(' ').unwrap();
if symbol.starts_with("_ZN") {
writeln!(
redefinitions_file,
"{} {}",
symbol,
symbol.replacen("_ZN", &replacement, 1)
)
.unwrap();
}
}
redefinitions_file.flush().unwrap();
drop(redefinitions_file);

assert!(
!child.wait().map(|s| !s.success()).unwrap_or(true),
"Couldn't link runtime crate! Do you have the llvm-tools component installed?"
);

let mut command = Command::new(rust_objcopy);

for symbol in [
"__rust_drop_panic",
"__rust_foreign_exception",
"rust_begin_unwind",
"rust_panic",
"rust_eh_personality",
"__rg_oom",
"__rdl_oom",
"__rdl_alloc",
"__rust_alloc",
"__rdl_dealloc",
"__rust_dealloc",
"__rdl_realloc",
"__rust_realloc",
"__rdl_alloc_zeroed",
"__rust_alloc_zeroed",
"__rust_alloc_error_handler",
"__rust_no_alloc_shim_is_unstable",
"__rust_alloc_error_handler_should_panic",
] {
command
.arg("--redefine-sym")
.arg(format!("{symbol}={symbol}_libafl_libfuzzer_runtime"));
}

command
.arg("--redefine-syms")
.arg(redefined_symbols)
.args([&objfile_orig, &objfile_dest]);

assert!(
!command.status().map(|s| !s.success()).unwrap_or(true),
"Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed?"
);

let mut command = Command::new(rust_ar);
command
.arg("cr")
.arg(custom_lib_dir.join("libFuzzer.a"))
.arg(objfile_dest);

assert!(
!command.status().map(|s| !s.success()).unwrap_or(true),
"Couldn't create runtime archive!"
);

#[cfg(feature = "embed-runtime")]
{
// NOTE: lib, .a are added always on unix-like systems as described in:
// https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b
println!(
"cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}",
custom_lib_dir.join("libFuzzer.a").display()
);
}

println!(
"cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}",
lib_path.join("libafl_libfuzzer_runtime.a").display()
"cargo:rustc-link-search=native={}",
custom_lib_dir.to_str().unwrap()
);
println!("cargo:rustc-link-lib=static=Fuzzer");
} else {
println!(
"cargo:rustc-link-search=native={}",
lib_path.to_str().unwrap()
);
println!("cargo:rustc-link-lib=static=afl_fuzzer_runtime");
}

println!(
"cargo:rustc-link-search=native={}",
lib_path.to_str().unwrap()
);
println!("cargo:rustc-link-lib=static=afl_libfuzzer_runtime");
println!("cargo:rustc-link-lib=stdc++");
}
2 changes: 1 addition & 1 deletion libafl_libfuzzer/libafl_libfuzzer_runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ libafl_targets = { path = "../../libafl_targets", features = ["sancov_8bit", "sa
ahash = { version = "0.8.3", default-features = false }
libc = "0.2.139"
log = "0.4.17"
mimalloc = { version = "0.1.34", default-features = false, optional = true }
mimalloc = { version = "0.1.34", default-features = false }
num-traits = "0.2.15"
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] } # serialization lib
Expand Down
1 change: 1 addition & 0 deletions libafl_libfuzzer/libafl_libfuzzer_runtime/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{env, path::Path};

#[allow(clippy::too_many_lines)]
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();

Expand Down
3 changes: 3 additions & 0 deletions libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ use libafl::{
};
use libafl_bolts::AsSlice;
use libc::_exit;
use mimalloc::MiMalloc;

use crate::options::{LibfuzzerMode, LibfuzzerOptions};
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

mod corpus;
mod feedbacks;
Expand Down