Skip to content

[asan] Implement interception on AIX #131870

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 6 additions & 1 deletion compiler-rt/lib/asan/asan_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,16 @@ struct Allocator {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
ReportInvalidFree(old_ptr, chunk_state, stack);
CHECK_NE(REAL(memcpy), nullptr);
uptr memcpy_size = Min(new_size, m->UsedSize());
// If realloc() races with free(), we may start copying freed memory.
// However, we will report racy double-free later anyway.
#if !SANITIZER_AIX
CHECK_NE(REAL(memcpy), nullptr);
REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
#else
// AIX does not intercept memcpy, we have to use internal_memcpy here.
internal_memcpy(new_ptr, old_ptr, memcpy_size);
#endif
Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC);
}
return new_ptr;
Expand Down
51 changes: 47 additions & 4 deletions compiler-rt/lib/asan/asan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace __asan {
# define ASAN_READ_STRING(ctx, s, n) \
ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))

# if ASAN_INTERCEPT_STRCAT || ASAN_INTERCEPT_STRCPY
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's use [[maybe_unused]] instead of #if

#if SANITIZER_INTERCEPT_STRNLEN
if (REAL(strnlen)) {
Expand All @@ -64,6 +65,7 @@ static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
#endif
return internal_strnlen(s, maxlen);
}
# endif

void SetThreadName(const char *name) {
AsanThread *t = GetCurrentThread();
Expand Down Expand Up @@ -275,7 +277,12 @@ INTERCEPTOR(int, pthread_create, void *thread, void *attr,
# endif
asanThreadArgRetval().Create(detached, {start_routine, arg}, [&]() -> uptr {
result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
// AIX pthread_t is unsigned int.
# if SANITIZER_AIX
return result ? 0 : *(unsigned int *)(thread);
# else
return result ? 0 : *(uptr *)(thread);
# endif
});
}
if (result != 0) {
Expand Down Expand Up @@ -432,12 +439,14 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
#define siglongjmp __siglongjmp14
#endif

# if ASAN_INTERCEPT_LONGJMP
INTERCEPTOR(void, longjmp, void *env, int val) {
__asan_handle_no_return();
REAL(longjmp)(env, val);
}
# endif

#if ASAN_INTERCEPT__LONGJMP
# if ASAN_INTERCEPT__LONGJMP
INTERCEPTOR(void, _longjmp, void *env, int val) {
__asan_handle_no_return();
REAL(_longjmp)(env, val);
Expand Down Expand Up @@ -508,6 +517,7 @@ DEFINE_REAL(char*, index, const char *string, int c)

// For both strcat() and strncat() we need to check the validity of |to|
// argument irrespective of the |from| length.
# if ASAN_INTERCEPT_STRCAT
INTERCEPTOR(char *, strcat, char *to, const char *from) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
Expand Down Expand Up @@ -547,7 +557,9 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, usize size) {
}
return REAL(strncat)(to, from, size);
}
# endif

# if ASAN_INTERCEPT_STRCPY
INTERCEPTOR(char *, strcpy, char *to, const char *from) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
Expand All @@ -569,6 +581,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) {
}
return REAL(strcpy)(to, from);
}
# endif

// Windows doesn't always define the strdup identifier,
// and when it does it's a macro defined to either _strdup
Expand Down Expand Up @@ -596,7 +609,13 @@ INTERCEPTOR(char*, strdup, const char *s) {
GET_STACK_TRACE_MALLOC;
void *new_mem = asan_malloc(length + 1, &stack);
if (new_mem) {
# if SANITIZER_AIX
// memcpy is a static function defined in libc.a on AIX. It can not be
// intercepted, so REAL(memcpy) is null on AIX. Use internal_memcpy instead.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you please extract inline internal_or_real_memcpy() in the top of the file?

Copy link
Collaborator

Choose a reason for hiding this comment

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

#if SANITIZER_INTERCEPT_MEMCPY rather than SANITIZER_AIX?

internal_memcpy(new_mem, s, length + 1);
# else
REAL(memcpy)(new_mem, s, length + 1);
# endif
}
return reinterpret_cast<char*>(new_mem);
}
Expand All @@ -614,12 +633,17 @@ INTERCEPTOR(char*, __strdup, const char *s) {
GET_STACK_TRACE_MALLOC;
void *new_mem = asan_malloc(length + 1, &stack);
if (new_mem) {
# if SANITIZER_AIX
internal_memcpy(new_mem, s, length + 1);
# else
REAL(memcpy)(new_mem, s, length + 1);
# endif
}
return reinterpret_cast<char*>(new_mem);
}
#endif // ASAN_INTERCEPT___STRDUP

# if ASAN_INTERCEPT_STRCPY
INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
Expand All @@ -632,6 +656,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) {
}
return REAL(strncpy)(to, from, size);
}
# endif

template <typename Fn>
static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
Expand Down Expand Up @@ -743,7 +768,15 @@ static void AtCxaAtexit(void *unused) {
}
#endif

#if ASAN_INTERCEPT___CXA_ATEXIT
# if ASAN_INTERCEPT_EXIT
INTERCEPTOR(void, exit, int status) {
AsanInitFromRtl();
StopInitOrderChecking();
REAL(exit)(status);
}
# endif

# if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
Expand Down Expand Up @@ -804,10 +837,14 @@ void InitializeAsanInterceptors() {
InitializeSignalInterceptors();

// Intercept str* functions.
# if ASAN_INTERCEPT_STRCAT
ASAN_INTERCEPT_FUNC(strcat);
ASAN_INTERCEPT_FUNC(strcpy);
ASAN_INTERCEPT_FUNC(strncat);
# endif
# if ASAN_INTERCEPT_STRCPY
ASAN_INTERCEPT_FUNC(strcpy);
ASAN_INTERCEPT_FUNC(strncpy);
# endif
ASAN_INTERCEPT_FUNC(strdup);
# if ASAN_INTERCEPT___STRDUP
ASAN_INTERCEPT_FUNC(__strdup);
Expand All @@ -827,7 +864,9 @@ void InitializeAsanInterceptors() {
# endif

// Intercept jump-related functions.
# if ASAN_INTERCEPT_LONGJMP
ASAN_INTERCEPT_FUNC(longjmp);
# endif

# if ASAN_INTERCEPT_SWAPCONTEXT
ASAN_INTERCEPT_FUNC(swapcontext);
Expand Down Expand Up @@ -894,7 +933,11 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(atexit);
#endif

#if ASAN_INTERCEPT_PTHREAD_ATFORK
# if ASAN_INTERCEPT_EXIT
ASAN_INTERCEPT_FUNC(exit);
# endif

# if ASAN_INTERCEPT_PTHREAD_ATFORK
ASAN_INTERCEPT_FUNC(pthread_atfork);
#endif

Expand Down
150 changes: 87 additions & 63 deletions compiler-rt/lib/asan/asan_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@ void InitializePlatformInterceptors();
// really defined to replace libc functions.
#if !SANITIZER_FUCHSIA

# if !SANITIZER_AIX
# define ASAN_INTERCEPT_LONGJMP 1
# else
# define ASAN_INTERCEPT_LONGJMP 0
# endif

// Use macro to describe if specific function should be
// intercepted on a given platform.
#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT__LONGJMP 1
# define ASAN_INTERCEPT_INDEX 1
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
# if !SANITIZER_AIX
# define ASAN_INTERCEPT__LONGJMP 1
# else
# define ASAN_INTERCEPT__LONGJMP 0
# endif
# define ASAN_INTERCEPT_INDEX 1
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
#else
# define ASAN_INTERCEPT__LONGJMP 0
# define ASAN_INTERCEPT_INDEX 0
Expand All @@ -56,73 +66,87 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_SWAPCONTEXT 0
#endif

#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_SIGLONGJMP 1
#else
# define ASAN_INTERCEPT_SIGLONGJMP 0
#endif

#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___LONGJMP_CHK 1
#else
# define ASAN_INTERCEPT___LONGJMP_CHK 0
#endif
# if !SANITIZER_WINDOWS && !SANITIZER_AIX
# define ASAN_INTERCEPT_SIGLONGJMP 1
# else
# define ASAN_INTERCEPT_SIGLONGJMP 0
# endif

#if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
# define ASAN_INTERCEPT___CXA_THROW 1
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
# else
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
# endif
#else
# define ASAN_INTERCEPT___CXA_THROW 0
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
#endif
# if SANITIZER_GLIBC
# define ASAN_INTERCEPT___LONGJMP_CHK 1
# else
# define ASAN_INTERCEPT___LONGJMP_CHK 0
# endif

# if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
# define ASAN_INTERCEPT___CXA_THROW 1
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
# else
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
# endif
# else
# define ASAN_INTERCEPT___CXA_THROW 0
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
# endif

# if !SANITIZER_WINDOWS && !SANITIZER_AIX
# define ASAN_INTERCEPT___CXA_ATEXIT 1
# else
# define ASAN_INTERCEPT___CXA_ATEXIT 0
# endif

#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT___CXA_ATEXIT 1
#else
# define ASAN_INTERCEPT___CXA_ATEXIT 0
#endif
# if SANITIZER_AIX
# define ASAN_INTERCEPT_EXIT 1
# else
# define ASAN_INTERCEPT_EXIT 0
# endif

#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
#else
# define ASAN_INTERCEPT_ATEXIT 0
#endif
# if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
# else
# define ASAN_INTERCEPT_ATEXIT 0
# endif

#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___STRDUP 1
#else
# define ASAN_INTERCEPT___STRDUP 0
#endif
# if SANITIZER_GLIBC
# define ASAN_INTERCEPT___STRDUP 1
# else
# define ASAN_INTERCEPT___STRDUP 0
# endif

#if SANITIZER_GLIBC && ASAN_INTERCEPT_PTHREAD_CREATE
# define ASAN_INTERCEPT_TIMEDJOIN 1
# define ASAN_INTERCEPT_TRYJOIN 1
#else
# define ASAN_INTERCEPT_TIMEDJOIN 0
# define ASAN_INTERCEPT_TRYJOIN 0
#endif
# if SANITIZER_GLIBC && ASAN_INTERCEPT_PTHREAD_CREATE
# define ASAN_INTERCEPT_TIMEDJOIN 1
# define ASAN_INTERCEPT_TRYJOIN 1
# else
# define ASAN_INTERCEPT_TIMEDJOIN 0
# define ASAN_INTERCEPT_TRYJOIN 0
# endif

#if SANITIZER_LINUX && \
(defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
# define ASAN_INTERCEPT_VFORK 1
#else
# define ASAN_INTERCEPT_VFORK 0
#endif
# if SANITIZER_AIX
# define ASAN_INTERCEPT_STRCAT 0
# define ASAN_INTERCEPT_STRCPY 0
# else
# define ASAN_INTERCEPT_STRCAT 1
# define ASAN_INTERCEPT_STRCPY 1
# endif

# if SANITIZER_LINUX && \
(defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
# define ASAN_INTERCEPT_VFORK 1
# else
# define ASAN_INTERCEPT_VFORK 0
# endif

#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
#else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
#endif
# if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
# else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
# endif

DECLARE_REAL(int, memcmp, const void *a1, const void *a2, SIZE_T size)
DECLARE_REAL(char*, strchr, const char *str, int c)
Expand Down
9 changes: 8 additions & 1 deletion compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@

using namespace __asan;

// AIX does not intercept memcpy, so we have to use internal_memcpy.
#if !SANITIZER_AIX
# define ASAN_MEMCPY_RETURN(to, from, size) REAL(memcpy)(to, from, size)
#else
# define ASAN_MEMCPY_RETURN(to, from, size) internal_memcpy(to, from, size)
#endif

// memcpy is called during __asan_init() from the internals of printf(...).
// We do not treat memcpy with to==from as a bug.
// See http://llvm.org/bugs/show_bug.cgi?id=11763.
Expand All @@ -36,7 +43,7 @@ using namespace __asan;
} else if (UNLIKELY(!AsanInited())) { \
return internal_memcpy(to, from, size); \
} \
return REAL(memcpy)(to, from, size); \
return ASAN_MEMCPY_RETURN(to, from, size); \
} while (0)

// memset is called inside Printf.
Expand Down
Loading
Loading