How to override AddressSanitizer callback functions (e.g. `__asan_on_error`)

89 views Asked by At

I'm trying to interact with interfaces of AddressSanitizer while using Rust, but I'm having some difficulties.

Specifically, I want to write a hook that is called immediately when ASan detects an error. For this purpose, I have tried to override __asan_on_error function as the following:

use std::hint::black_box;

#[no_mangle]
pub extern "C" fn __asan_on_error() -> libc::c_void {
    std::process::abort();
}

fn main() {
    let ptr = Box::into_raw(Box::new(1));
    unsafe { drop(Box::from_raw(ptr)) };
    black_box(unsafe { *black_box(ptr) } + 1);
}

Run with:

RUSTFLAGS="-Z sanitizer=address" cargo run --profile=dev --target aarch64-apple-darwin

The intended result of the code above would be aborting the program before printing error messages. However, it does not abort the program and prints all logs for the error.

It gives me headache because an equivalant code written in C++ works as intended (abort before printing the logs).

#include <sanitizer/asan_interface.h>
#include <cstdlib>

extern "C" void __asan_on_error() {
    abort();
}

int main(int argc, char **argv) {
    volatile int* ptr = (int*)std::malloc(sizeof(int));
    std::free((void*)ptr);
    volatile int _ = *ptr + 1;
}

Run with:

clang -o main -x c++ -O -g -fsanitize=address main.cpp && ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer) ./main

In summary, my question is the following:

Is it possible to override AddressSanitizer callback functions in Rust? If so, how to do that, and what did I miss?


Additionally, I tried calling other functions in asan_interface.h, such as __asan_describe_address, to find out whether the Rust compiler is linking my binary to the ASan library or not. For example, I have written an experimental code like the following:

extern "C" {
    fn __asan_describe_address(addr: *mut libc::c_void) -> libc::c_void;
}

fn main() {
    let ptr = Box::into_raw(Box::new(1));
    unsafe { __asan_describe_address(ptr as _) };
}

Run with:

RUSTFLAGS="-Z sanitizer=address" cargo run --profile=dev --target aarch64-apple-darwin

Surprisingly, it actually works, printing out the logs about the given pointer. It proves that it is possible to call ASan function from the Rust, but the callback implementation in Rust is not recognized by the ASan library for some reasons, even though it has both #[no_mangle] and pub extern "C".

0

There are 0 answers