Skip to content

Commit

Permalink
libsanitizer: merge from master
Browse files Browse the repository at this point in the history
Merged revision: f58e051
  • Loading branch information
marxin committed May 13, 2021
1 parent 810afb0 commit d0fee87
Show file tree
Hide file tree
Showing 153 changed files with 2,538 additions and 1,239 deletions.
2 changes: 1 addition & 1 deletion libsanitizer/MERGE
@@ -1,4 +1,4 @@
6e7dd1e3e1170080b76b5dcc5716bdd974343233
f58e0513dd95944b81ce7a6e7b49ba656de7d75f

The first line of this file holds the git revision number of the
last merge done from the master library sources.
32 changes: 30 additions & 2 deletions libsanitizer/asan/asan_allocator.cpp
Expand Up @@ -476,7 +476,7 @@ struct Allocator {
return false;
if (m->Beg() != addr) return false;
AsanThread *t = GetCurrentThread();
m->SetAllocContext(t ? t->tid() : 0, StackDepotPut(*stack));
m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));
return true;
}

Expand Down Expand Up @@ -570,7 +570,7 @@ struct Allocator {
m->SetUsedSize(size);
m->user_requested_alignment_log = user_requested_alignment_log;

m->SetAllocContext(t ? t->tid() : 0, StackDepotPut(*stack));
m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));

uptr size_rounded_down_to_granularity =
RoundDownTo(size, SHADOW_GRANULARITY);
Expand Down Expand Up @@ -1183,6 +1183,34 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
m->lsan_tag = __lsan::kIgnored;
return kIgnoreObjectSuccess;
}

void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) {
// Look for the arg pointer of threads that have been created or are running.
// This is necessary to prevent false positive leaks due to the AsanThread
// holding the only live reference to a heap object. This can happen because
// the `pthread_create()` interceptor doesn't wait for the child thread to
// start before returning and thus loosing the the only live reference to the
// heap object on the stack.

__asan::AsanThreadContext *atctx =
reinterpret_cast<__asan::AsanThreadContext *>(tctx);
__asan::AsanThread *asan_thread = atctx->thread;

// Note ThreadStatusRunning is required because there is a small window where
// the thread status switches to `ThreadStatusRunning` but the `arg` pointer
// still isn't on the stack yet.
if (atctx->status != ThreadStatusCreated &&
atctx->status != ThreadStatusRunning)
return;

uptr thread_arg = reinterpret_cast<uptr>(asan_thread->get_arg());
if (!thread_arg)
return;

auto ptrsVec = reinterpret_cast<InternalMmapVector<uptr> *>(ptrs);
ptrsVec->push_back(thread_arg);
}

} // namespace __lsan

// ---------------------- Interface ---------------- {{{1
Expand Down
19 changes: 12 additions & 7 deletions libsanitizer/asan/asan_descriptions.cpp
Expand Up @@ -44,11 +44,11 @@ void DescribeThread(AsanThreadContext *context) {
CHECK(context);
asanThreadRegistry().CheckLocked();
// No need to announce the main thread.
if (context->tid == 0 || context->announced) {
if (context->tid == kMainTid || context->announced) {
return;
}
context->announced = true;
InternalScopedString str(1024);
InternalScopedString str;
str.append("Thread %s", AsanThreadIdAndName(context).c_str());
if (context->parent_tid == kInvalidTid) {
str.append(" created by unknown thread\n");
Expand Down Expand Up @@ -77,7 +77,6 @@ static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) {
} else if (AddrIsInLowShadow(addr)) {
*shadow_kind = kShadowKindLow;
} else {
CHECK(0 && "Address is not in memory and not in shadow?");
return false;
}
return true;
Expand Down Expand Up @@ -126,7 +125,7 @@ static void GetAccessToHeapChunkInformation(ChunkAccess *descr,

static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
Decorator d;
InternalScopedString str(4096);
InternalScopedString str;
str.append("%s", d.Location());
switch (descr.access_type) {
case kAccessTypeLeft:
Expand Down Expand Up @@ -243,7 +242,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end)
pos_descr = "underflows";
}
InternalScopedString str(1024);
InternalScopedString str;
str.append(" [%zd, %zd)", var.beg, var_end);
// Render variable name.
str.append(" '");
Expand Down Expand Up @@ -276,7 +275,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
// Global descriptions
static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
const __asan_global &g) {
InternalScopedString str(4096);
InternalScopedString str;
Decorator d;
str.append("%s", d.Location());
if (addr < g.beg) {
Expand Down Expand Up @@ -464,7 +463,13 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size,
return;
}
data.kind = kAddressKindWild;
addr = 0;
data.wild.addr = addr;
data.wild.access_size = access_size;
}

void WildAddressDescription::Print() const {
Printf("Address %p is a wild pointer inside of access range of size %p.\n",
addr, access_size);
}

void PrintAddressDescription(uptr addr, uptr access_size,
Expand Down
13 changes: 10 additions & 3 deletions libsanitizer/asan/asan_descriptions.h
Expand Up @@ -146,6 +146,13 @@ struct StackAddressDescription {
bool GetStackAddressInformation(uptr addr, uptr access_size,
StackAddressDescription *descr);

struct WildAddressDescription {
uptr addr;
uptr access_size;

void Print() const;
};

struct GlobalAddressDescription {
uptr addr;
// Assume address is close to at most four globals.
Expand Down Expand Up @@ -193,7 +200,7 @@ class AddressDescription {
HeapAddressDescription heap;
StackAddressDescription stack;
GlobalAddressDescription global;
uptr addr;
WildAddressDescription wild;
};
};

Expand All @@ -211,7 +218,7 @@ class AddressDescription {
uptr Address() const {
switch (data.kind) {
case kAddressKindWild:
return data.addr;
return data.wild.addr;
case kAddressKindShadow:
return data.shadow.addr;
case kAddressKindHeap:
Expand All @@ -226,7 +233,7 @@ class AddressDescription {
void Print(const char *bug_descr = nullptr) const {
switch (data.kind) {
case kAddressKindWild:
Printf("Address %p is a wild pointer.\n", data.addr);
data.wild.Print();
return;
case kAddressKindShadow:
return data.shadow.Print();
Expand Down
7 changes: 4 additions & 3 deletions libsanitizer/asan/asan_errors.cpp
Expand Up @@ -343,7 +343,8 @@ void ErrorODRViolation::Print() {
Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
global1.beg);
Printf("%s", d.Default());
InternalScopedString g1_loc(256), g2_loc(256);
InternalScopedString g1_loc;
InternalScopedString g2_loc;
PrintGlobalLocation(&g1_loc, global1);
PrintGlobalLocation(&g2_loc, global2);
Printf(" [1] size=%zd '%s' %s\n", global1.size,
Expand All @@ -360,7 +361,7 @@ void ErrorODRViolation::Print() {
Report(
"HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
InternalScopedString error_msg(256);
InternalScopedString error_msg;
error_msg.append("%s: global '%s' at %s", scariness.GetDescription(),
MaybeDemangleGlobalName(global1.name), g1_loc.data());
ReportErrorSummary(error_msg.data());
Expand Down Expand Up @@ -554,7 +555,7 @@ static void PrintShadowMemoryForAddress(uptr addr) {
uptr shadow_addr = MemToShadow(addr);
const uptr n_bytes_per_row = 16;
uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
InternalScopedString str(4096 * 8);
InternalScopedString str;
str.append("Shadow bytes around the buggy address:\n");
for (int i = -5; i <= 5; i++) {
uptr row_shadow_addr = aligned_shadow + i * n_bytes_per_row;
Expand Down
2 changes: 1 addition & 1 deletion libsanitizer/asan/asan_fake_stack.cpp
Expand Up @@ -65,7 +65,7 @@ FakeStack *FakeStack::Create(uptr stack_size_log) {
void FakeStack::Destroy(int tid) {
PoisonAll(0);
if (Verbosity() >= 2) {
InternalScopedString str(kNumberOfSizeClasses * 50);
InternalScopedString str;
for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++)
str.append("%zd: %zd/%zd; ", class_id, hint_position_[class_id],
NumberOfFrames(stack_size_log(), class_id));
Expand Down
2 changes: 1 addition & 1 deletion libsanitizer/asan/asan_fuchsia.cpp
Expand Up @@ -81,7 +81,7 @@ void AsanTSDInit(void (*destructor)(void *tsd)) {
void PlatformTSDDtor(void *tsd) { UNREACHABLE(__func__); }

static inline size_t AsanThreadMmapSize() {
return RoundUpTo(sizeof(AsanThread), PAGE_SIZE);
return RoundUpTo(sizeof(AsanThread), _zx_system_get_page_size());
}

struct AsanThread::InitOptions {
Expand Down
19 changes: 19 additions & 0 deletions libsanitizer/asan/asan_globals.cpp
Expand Up @@ -154,6 +154,23 @@ static void CheckODRViolationViaIndicator(const Global *g) {
}
}

// Check ODR violation for given global G by checking if it's already poisoned.
// We use this method in case compiler doesn't use private aliases for global
// variables.
static void CheckODRViolationViaPoisoning(const Global *g) {
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
// This check may not be enough: if the first global is much larger
// the entire redzone of the second global may be within the first global.
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
if (g->beg == l->g->beg &&
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
!IsODRViolationSuppressed(g->name))
ReportODRViolation(g, FindRegistrationSite(g),
l->g, FindRegistrationSite(l->g));
}
}
}

// Clang provides two different ways for global variables protection:
// it can poison the global itself or its private alias. In former
// case we may poison same symbol multiple times, that can help us to
Expand Down Expand Up @@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) {
// where two globals with the same name are defined in different modules.
if (UseODRIndicator(g))
CheckODRViolationViaIndicator(g);
else
CheckODRViolationViaPoisoning(g);
}
if (CanPoisonMemory())
PoisonRedZones(*g);
Expand Down
41 changes: 13 additions & 28 deletions libsanitizer/asan/asan_interceptors.cpp
Expand Up @@ -191,20 +191,11 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
#include "sanitizer_common/sanitizer_common_syscalls.inc"
#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"

struct ThreadStartParam {
atomic_uintptr_t t;
atomic_uintptr_t is_registered;
};

#if ASAN_INTERCEPT_PTHREAD_CREATE
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
AsanThread *t = nullptr;
while ((t = reinterpret_cast<AsanThread *>(
atomic_load(&param->t, memory_order_acquire))) == nullptr)
internal_sched_yield();
AsanThread *t = (AsanThread *)arg;
SetCurrentThread(t);
return t->ThreadStart(GetTid(), &param->is_registered);
return t->ThreadStart(GetTid());
}

INTERCEPTOR(int, pthread_create, void *thread,
Expand All @@ -217,9 +208,11 @@ INTERCEPTOR(int, pthread_create, void *thread,
int detached = 0;
if (attr)
REAL(pthread_attr_getdetachstate)(attr, &detached);
ThreadStartParam param;
atomic_store(&param.t, 0, memory_order_relaxed);
atomic_store(&param.is_registered, 0, memory_order_relaxed);

u32 current_tid = GetCurrentTidOrInvalid();
AsanThread *t =
AsanThread::Create(start_routine, arg, current_tid, &stack, detached);

int result;
{
// Ignore all allocations made by pthread_create: thread stack/TLS may be
Expand All @@ -229,21 +222,13 @@ INTERCEPTOR(int, pthread_create, void *thread,
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
}
if (result == 0) {
u32 current_tid = GetCurrentTidOrInvalid();
AsanThread *t =
AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
// Wait until the AsanThread object is initialized and the ThreadRegistry
// entry is in "started" state. One reason for this is that after this
// interceptor exits, the child thread's stack may be the only thing holding
// the |arg| pointer. This may cause LSan to report a leak if leak checking
// happens at a point when the interceptor has already exited, but the stack
// range for the child thread is not yet known.
while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
internal_sched_yield();
if (result != 0) {
// If the thread didn't start delete the AsanThread to avoid leaking it.
// Note AsanThreadContexts never get destroyed so the AsanThreadContext
// that was just created for the AsanThread is wasted.
t->Destroy();
}
return result;
}
Expand Down
21 changes: 8 additions & 13 deletions libsanitizer/asan/asan_interceptors.h
Expand Up @@ -60,7 +60,7 @@ void InitializePlatformInterceptors();
# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
#endif

#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_SOLARIS
#if SANITIZER_GLIBC || SANITIZER_SOLARIS
# define ASAN_INTERCEPT_SWAPCONTEXT 1
#else
# define ASAN_INTERCEPT_SWAPCONTEXT 0
Expand All @@ -72,7 +72,7 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_SIGLONGJMP 0
#endif

#if SANITIZER_LINUX && !SANITIZER_ANDROID
#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___LONGJMP_CHK 1
#else
# define ASAN_INTERCEPT___LONGJMP_CHK 0
Expand All @@ -81,12 +81,7 @@ void InitializePlatformInterceptors();
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
!SANITIZER_NETBSD
# define ASAN_INTERCEPT___CXA_THROW 1
# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \
|| ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# else
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# endif
# 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
Expand All @@ -111,7 +106,7 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_ATEXIT 0
#endif

#if SANITIZER_LINUX && !SANITIZER_ANDROID
#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___STRDUP 1
#else
# define ASAN_INTERCEPT___STRDUP 0
Expand Down Expand Up @@ -139,10 +134,10 @@ DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)

#if !SANITIZER_MAC
#define ASAN_INTERCEPT_FUNC(name) \
do { \
if (!INTERCEPT_FUNCTION(name)) \
VReport(1, "AddressSanitizer: failed to intercept '%s'\n'", #name); \
#define ASAN_INTERCEPT_FUNC(name) \
do { \
if (!INTERCEPT_FUNCTION(name)) \
VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
} while (0)
#define ASAN_INTERCEPT_FUNC_VER(name, ver) \
do { \
Expand Down
3 changes: 2 additions & 1 deletion libsanitizer/asan/asan_linux.cpp
Expand Up @@ -55,6 +55,7 @@ extern Elf_Dyn _DYNAMIC;
#else
#include <sys/ucontext.h>
#include <link.h>
extern ElfW(Dyn) _DYNAMIC[];
#endif

// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
Expand Down Expand Up @@ -84,7 +85,7 @@ bool IsSystemHeapAddress (uptr addr) { return false; }

void *AsanDoesNotSupportStaticLinkage() {
// This will fail to link with -static.
return &_DYNAMIC; // defined in link.h
return &_DYNAMIC;
}

#if ASAN_PREMAP_SHADOW
Expand Down

0 comments on commit d0fee87

Please sign in to comment.