Skip to content
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

Disable ASAN in ffi_call_int functions #858

Merged
merged 1 commit into from
Sep 20, 2024
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
Disable ASAN in ffi_call_int functions
The pattern for several of the architectures is for ffi_call_int to
stack-allocate some arguments + the registers, and then
ffi_call_$ARCH will pop the top of that structure into registers, and
then adjust the stack pointer such that the alloca'd buffer _becomes_
the stack-passed arguments for the function being called.

If libffi is compiled with ASAN, then there will be a redzone inserted
after the alloca'd buffer which is marked as poisoned. This redzone
appears beyond the end of $sp upon entry to the called function.

If the called function does anything to use this stack memory, ASAN will
notice that it's poisoned and report an error.

This commit fixes the situation (on the architectures that I have access
to) disabling instrumentation for ffi_call_int; that means there will be
no alloca redzone left on the shadow-stack.
  • Loading branch information
KJ Tsanaktsidis authored and KJTsanaktsidis committed Sep 17, 2024
commit 55f98c71d4f3dc4fe7b25d8b7447b2d06be9f3f0
17 changes: 17 additions & 0 deletions include/ffi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ char *alloca ();
#include <stdio.h>
#endif

#ifndef __SANITIZE_ADDRESS__
# ifdef __clang__
# if __has_feature(address_sanitizer)
# define FFI_ASAN
# endif
# endif
#endif
#ifdef __SANITIZE_ADDRESS__
#define FFI_ASAN
#endif

#ifdef FFI_ASAN
#define FFI_ASAN_NO_SANITIZE __attribute__((no_sanitize_address))
#else
#define FFI_ASAN_NO_SANITIZE
#endif

#ifdef FFI_DEBUG
NORETURN void ffi_assert(const char *expr, const char *file, int line);
void ffi_stop_here(void);
Expand Down
5 changes: 4 additions & 1 deletion src/aarch64/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,10 @@ extern void ffi_call_SYSV (struct call_context *context, void *frame,
void *closure) FFI_HIDDEN;

/* Call a function with the provided arguments and capture the return
value. */
value.
n.b. ffi_call_SYSV will steal the alloca'd `stack` variable here for use
_as its own stack_ - so we need to compile this function without ASAN */
FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
void **avalue, void *closure)
Expand Down
3 changes: 3 additions & 0 deletions src/x86/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_
#if defined(_MSC_VER)
#pragma runtime_checks("s", off)
#endif
/* n.b. ffi_call_unix64 will steal the alloca'd `stack` variable here for use
_as its own stack_ - so we need to compile this function without ASAN */
FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
Expand Down
3 changes: 3 additions & 0 deletions src/x86/ffi64.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,9 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK;
}

/* n.b. ffi_call_unix64 will steal the alloca'd `stack` variable here for use
_as its own stack_ - so we need to compile this function without ASAN */
FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
Expand Down
Loading