forked from OSchip/llvm-project
[msan] Fix false positive on dynamic tls.
Use existing DTLS code in sanitizer_tls_get_addr.{h,cc} to unpoison DTLS blocks both on allocation and deallocation. https://code.google.com/p/memory-sanitizer/issues/detail?id=44 llvm-svn: 211683
This commit is contained in:
parent
f48f0620ed
commit
7ad0bde843
|
@ -162,6 +162,7 @@ static void InitializeFlags(Flags *f, const char *options) {
|
|||
cf->handle_ioctl = true;
|
||||
// FIXME: test and enable.
|
||||
cf->check_printf = false;
|
||||
cf->intercept_tls_get_addr = true;
|
||||
|
||||
internal_memset(f, 0, sizeof(*f));
|
||||
f->poison_heap_with_zeroes = false;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_linux.h"
|
||||
#include "sanitizer_common/sanitizer_tls_get_addr.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
// ACHTUNG! No other system header includes in this file.
|
||||
|
@ -161,8 +162,13 @@ INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, __libc_memalign, uptr align, uptr s)
|
||||
ALIAS(WRAPPER_NAME(memalign));
|
||||
INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
CHECK_EQ(boundary & (boundary - 1), 0);
|
||||
void *ptr = MsanReallocate(&stack, 0, size, boundary, false);
|
||||
DTLS_on_libc_memalign(ptr, size * boundary);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, valloc, SIZE_T size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
|
@ -1459,6 +1465,7 @@ void InitializeInterceptors() {
|
|||
INTERCEPT_FUNCTION(mmap64);
|
||||
INTERCEPT_FUNCTION(posix_memalign);
|
||||
INTERCEPT_FUNCTION(memalign);
|
||||
INTERCEPT_FUNCTION(__libc_memalign);
|
||||
INTERCEPT_FUNCTION(valloc);
|
||||
INTERCEPT_FUNCTION(pvalloc);
|
||||
INTERCEPT_FUNCTION(malloc);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "msan_thread.h"
|
||||
#include "msan_interface_internal.h"
|
||||
|
||||
#include "sanitizer_common/sanitizer_tls_get_addr.h"
|
||||
|
||||
namespace __msan {
|
||||
|
||||
MsanThread *MsanThread::Create(thread_callback_t start_routine,
|
||||
|
@ -33,6 +35,9 @@ void MsanThread::ClearShadowForThreadStackAndTLS() {
|
|||
__msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);
|
||||
if (tls_begin_ != tls_end_)
|
||||
__msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
|
||||
DTLS *dtls = DTLS_Get();
|
||||
for (uptr i = 0; i < dtls->dtv_size; ++i)
|
||||
__msan_unpoison((void *)(dtls->dtv[i].beg), dtls->dtv[i].size);
|
||||
}
|
||||
|
||||
void MsanThread::Init() {
|
||||
|
@ -55,6 +60,7 @@ void MsanThread::Destroy() {
|
|||
ClearShadowForThreadStackAndTLS();
|
||||
uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
|
||||
UnmapOrDie(this, size);
|
||||
DTLS_Destroy();
|
||||
}
|
||||
|
||||
thread_return_t MsanThread::ThreadStart() {
|
||||
|
|
|
@ -3827,7 +3827,11 @@ INTERCEPTOR(void *, __tls_get_addr, void *arg) {
|
|||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
|
||||
void *res = REAL(__tls_get_addr)(arg);
|
||||
DTLS_on_tls_get_addr(arg, res);
|
||||
DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res);
|
||||
if (dtv) {
|
||||
// New DTLS block has been allocated.
|
||||
COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -78,14 +78,13 @@ void DTLS_Destroy() {
|
|||
DTLS_Deallocate(dtls.dtv, s);
|
||||
}
|
||||
|
||||
void DTLS_on_tls_get_addr(void *arg_void, void *res) {
|
||||
if (!common_flags()->intercept_tls_get_addr) return;
|
||||
DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res) {
|
||||
if (!common_flags()->intercept_tls_get_addr) return 0;
|
||||
TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
|
||||
uptr dso_id = arg->dso_id;
|
||||
if (dtls.dtv_size == kDestroyedThread) return;
|
||||
if (dtls.dtv_size == kDestroyedThread) return 0;
|
||||
DTLS_Resize(dso_id + 1);
|
||||
if (dtls.dtv[dso_id].beg)
|
||||
return;
|
||||
if (dtls.dtv[dso_id].beg) return 0;
|
||||
uptr tls_size = 0;
|
||||
uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset;
|
||||
VPrintf(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
|
||||
|
@ -110,6 +109,7 @@ void DTLS_on_tls_get_addr(void *arg_void, void *res) {
|
|||
}
|
||||
dtls.dtv[dso_id].beg = tls_beg;
|
||||
dtls.dtv[dso_id].size = tls_size;
|
||||
return dtls.dtv + dso_id;
|
||||
}
|
||||
|
||||
void DTLS_on_libc_memalign(void *ptr, uptr size) {
|
||||
|
|
|
@ -48,7 +48,9 @@ struct DTLS {
|
|||
uptr last_memalign_ptr;
|
||||
};
|
||||
|
||||
void DTLS_on_tls_get_addr(void *arg, void *res);
|
||||
// Returns pointer and size of a linker-allocated TLS block.
|
||||
// Each block is returned exactly once.
|
||||
DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res);
|
||||
void DTLS_on_libc_memalign(void *ptr, uptr size);
|
||||
DTLS *DTLS_Get();
|
||||
void DTLS_Destroy(); // Make sure to call this before the thread is destroyed.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* RUN: %clang_msan -m64 %s -o %t
|
||||
RUN: %clang_msan -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
|
||||
RUN: not %run %t 2>&1 | FileCheck %s
|
||||
CHECK: MemorySanitizer: use-of-uninitialized-value
|
||||
/* RUN: %clang_msan -g -m64 %s -o %t
|
||||
RUN: %clang_msan -g -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
|
||||
RUN: %run %t 2>&1
|
||||
|
||||
This is an actual bug in msan/glibc integration,
|
||||
Regression test for a bug in msan/glibc integration,
|
||||
see https://sourceware.org/bugzilla/show_bug.cgi?id=16291
|
||||
and https://code.google.com/p/memory-sanitizer/issues/detail?id=44
|
||||
*/
|
||||
|
||||
#ifndef BUILD_SO
|
||||
|
|
Loading…
Reference in New Issue