[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:
Evgeniy Stepanov 2014-06-25 11:30:35 +00:00
parent f48f0620ed
commit 7ad0bde843
7 changed files with 34 additions and 14 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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() {

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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