mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 04:14:03 +08:00
[asan] Reset stack bounds of context
ClearShadowMemoryForContextStack assumes that context contains the stack bounds. This is not true for a context from getcontext or oucp of swapcontext. Reviewed By: kstoimenov Differential Revision: https://reviews.llvm.org/D130218
This commit is contained in:
@@ -253,6 +253,14 @@ static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
|
||||
PoisonShadow(bottom, ssize, 0);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, getcontext, struct ucontext_t *ucp) {
|
||||
// API does not requires to have ucp clean, and sets only part of fields. We
|
||||
// use ucp->uc_stack to unpoison new stack. We prefer to have zeroes then
|
||||
// uninitialized bytes.
|
||||
ResetContextStack(ucp);
|
||||
return REAL(getcontext)(ucp);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
|
||||
struct ucontext_t *ucp) {
|
||||
static bool reported_warning = false;
|
||||
@@ -266,6 +274,10 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
|
||||
uptr stack, ssize;
|
||||
ReadContextStack(ucp, &stack, &ssize);
|
||||
ClearShadowMemoryForContextStack(stack, ssize);
|
||||
|
||||
// See getcontext interceptor.
|
||||
ResetContextStack(oucp);
|
||||
|
||||
# if __has_attribute(__indirect_return__) && \
|
||||
(defined(__x86_64__) || defined(__i386__))
|
||||
int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
|
||||
@@ -643,6 +655,7 @@ void InitializeAsanInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(longjmp);
|
||||
|
||||
#if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
ASAN_INTERCEPT_FUNC(getcontext);
|
||||
ASAN_INTERCEPT_FUNC(swapcontext);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT__LONGJMP
|
||||
|
||||
@@ -106,6 +106,7 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle);
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context);
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
|
||||
void ResetContextStack(void *context);
|
||||
void StopInitOrderChecking();
|
||||
|
||||
// Wrapper for TLS/TSD.
|
||||
|
||||
@@ -214,11 +214,19 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
*stack = (uptr)ucp->uc_stack.ss_sp;
|
||||
*ssize = ucp->uc_stack.ss_size;
|
||||
}
|
||||
#else
|
||||
|
||||
void ResetContextStack(void *context) {
|
||||
ucontext_t *ucp = (ucontext_t *)context;
|
||||
ucp->uc_stack.ss_sp = nullptr;
|
||||
ucp->uc_stack.ss_size = 0;
|
||||
}
|
||||
# else
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ResetContextStack(void *context) { UNIMPLEMENTED(); }
|
||||
# endif
|
||||
|
||||
void *AsanDlSymNext(const char *sym) {
|
||||
return dlsym(RTLD_NEXT, sym);
|
||||
|
||||
@@ -99,6 +99,8 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void ResetContextStack(void *context) { UNIMPLEMENTED(); }
|
||||
|
||||
// Support for the following functions from libdispatch on Mac OS:
|
||||
// dispatch_async_f()
|
||||
// dispatch_async()
|
||||
|
||||
@@ -267,6 +267,8 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void ResetContextStack(void *context) { UNIMPLEMENTED(); }
|
||||
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); }
|
||||
|
||||
bool PlatformUnpoisonStacks() { return false; }
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
// Android and musl do not support swapcontext.
|
||||
// REQUIRES: x86-target-arch && glibc-2.27
|
||||
|
||||
#include <assert.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
@@ -33,6 +35,7 @@ void ThrowAndCatch() {
|
||||
}
|
||||
|
||||
void Child(int mode) {
|
||||
assert(orig_context.uc_stack.ss_size == 0);
|
||||
char x[32] = {0}; // Stack gets poisoned.
|
||||
printf("Child: %p\n", x);
|
||||
ThrowAndCatch(); // Simulate __asan_handle_no_return().
|
||||
@@ -50,13 +53,16 @@ void Child(int mode) {
|
||||
int Run(int arg, int mode, char *child_stack) {
|
||||
printf("Child stack: %p\n", child_stack);
|
||||
// Setup child context.
|
||||
memset(&child_context, 0xff, sizeof(child_context));
|
||||
getcontext(&child_context);
|
||||
assert(child_context.uc_stack.ss_size == 0);
|
||||
child_context.uc_stack.ss_sp = child_stack;
|
||||
child_context.uc_stack.ss_size = kStackSize / 2;
|
||||
if (mode == 0) {
|
||||
child_context.uc_link = &orig_context;
|
||||
}
|
||||
makecontext(&child_context, (void (*)())Child, 1, mode);
|
||||
memset(&orig_context, 0xff, sizeof(orig_context));
|
||||
if (swapcontext(&orig_context, &child_context) < 0) {
|
||||
perror("swapcontext");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user