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;
 | 
					  cf->handle_ioctl = true;
 | 
				
			||||||
  // FIXME: test and enable.
 | 
					  // FIXME: test and enable.
 | 
				
			||||||
  cf->check_printf = false;
 | 
					  cf->check_printf = false;
 | 
				
			||||||
 | 
					  cf->intercept_tls_get_addr = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  internal_memset(f, 0, sizeof(*f));
 | 
					  internal_memset(f, 0, sizeof(*f));
 | 
				
			||||||
  f->poison_heap_with_zeroes = false;
 | 
					  f->poison_heap_with_zeroes = false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@
 | 
				
			||||||
#include "sanitizer_common/sanitizer_stackdepot.h"
 | 
					#include "sanitizer_common/sanitizer_stackdepot.h"
 | 
				
			||||||
#include "sanitizer_common/sanitizer_libc.h"
 | 
					#include "sanitizer_common/sanitizer_libc.h"
 | 
				
			||||||
#include "sanitizer_common/sanitizer_linux.h"
 | 
					#include "sanitizer_common/sanitizer_linux.h"
 | 
				
			||||||
 | 
					#include "sanitizer_common/sanitizer_tls_get_addr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
// ACHTUNG! No other system header includes in this file.
 | 
					// ACHTUNG! No other system header includes in this file.
 | 
				
			||||||
| 
						 | 
					@ -161,8 +162,13 @@ INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) {
 | 
				
			||||||
  return ptr;
 | 
					  return ptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INTERCEPTOR(void *, __libc_memalign, uptr align, uptr s)
 | 
					INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) {
 | 
				
			||||||
    ALIAS(WRAPPER_NAME(memalign));
 | 
					  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) {
 | 
					INTERCEPTOR(void *, valloc, SIZE_T size) {
 | 
				
			||||||
  GET_MALLOC_STACK_TRACE;
 | 
					  GET_MALLOC_STACK_TRACE;
 | 
				
			||||||
| 
						 | 
					@ -1459,6 +1465,7 @@ void InitializeInterceptors() {
 | 
				
			||||||
  INTERCEPT_FUNCTION(mmap64);
 | 
					  INTERCEPT_FUNCTION(mmap64);
 | 
				
			||||||
  INTERCEPT_FUNCTION(posix_memalign);
 | 
					  INTERCEPT_FUNCTION(posix_memalign);
 | 
				
			||||||
  INTERCEPT_FUNCTION(memalign);
 | 
					  INTERCEPT_FUNCTION(memalign);
 | 
				
			||||||
 | 
					  INTERCEPT_FUNCTION(__libc_memalign);
 | 
				
			||||||
  INTERCEPT_FUNCTION(valloc);
 | 
					  INTERCEPT_FUNCTION(valloc);
 | 
				
			||||||
  INTERCEPT_FUNCTION(pvalloc);
 | 
					  INTERCEPT_FUNCTION(pvalloc);
 | 
				
			||||||
  INTERCEPT_FUNCTION(malloc);
 | 
					  INTERCEPT_FUNCTION(malloc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,8 @@
 | 
				
			||||||
#include "msan_thread.h"
 | 
					#include "msan_thread.h"
 | 
				
			||||||
#include "msan_interface_internal.h"
 | 
					#include "msan_interface_internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sanitizer_common/sanitizer_tls_get_addr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace __msan {
 | 
					namespace __msan {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MsanThread *MsanThread::Create(thread_callback_t start_routine,
 | 
					MsanThread *MsanThread::Create(thread_callback_t start_routine,
 | 
				
			||||||
| 
						 | 
					@ -33,6 +35,9 @@ void MsanThread::ClearShadowForThreadStackAndTLS() {
 | 
				
			||||||
  __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);
 | 
					  __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);
 | 
				
			||||||
  if (tls_begin_ != tls_end_)
 | 
					  if (tls_begin_ != tls_end_)
 | 
				
			||||||
    __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
 | 
					    __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() {
 | 
					void MsanThread::Init() {
 | 
				
			||||||
| 
						 | 
					@ -55,6 +60,7 @@ void MsanThread::Destroy() {
 | 
				
			||||||
  ClearShadowForThreadStackAndTLS();
 | 
					  ClearShadowForThreadStackAndTLS();
 | 
				
			||||||
  uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
 | 
					  uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
 | 
				
			||||||
  UnmapOrDie(this, size);
 | 
					  UnmapOrDie(this, size);
 | 
				
			||||||
 | 
					  DTLS_Destroy();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
thread_return_t MsanThread::ThreadStart() {
 | 
					thread_return_t MsanThread::ThreadStart() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3827,7 +3827,11 @@ INTERCEPTOR(void *, __tls_get_addr, void *arg) {
 | 
				
			||||||
  void *ctx;
 | 
					  void *ctx;
 | 
				
			||||||
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
 | 
				
			||||||
  void *res = REAL(__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;
 | 
					  return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,14 +78,13 @@ void DTLS_Destroy() {
 | 
				
			||||||
  DTLS_Deallocate(dtls.dtv, s);
 | 
					  DTLS_Deallocate(dtls.dtv, s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DTLS_on_tls_get_addr(void *arg_void, void *res) {
 | 
					DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res) {
 | 
				
			||||||
  if (!common_flags()->intercept_tls_get_addr) return;
 | 
					  if (!common_flags()->intercept_tls_get_addr) return 0;
 | 
				
			||||||
  TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
 | 
					  TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
 | 
				
			||||||
  uptr dso_id = arg->dso_id;
 | 
					  uptr dso_id = arg->dso_id;
 | 
				
			||||||
  if (dtls.dtv_size == kDestroyedThread) return;
 | 
					  if (dtls.dtv_size == kDestroyedThread) return 0;
 | 
				
			||||||
  DTLS_Resize(dso_id + 1);
 | 
					  DTLS_Resize(dso_id + 1);
 | 
				
			||||||
  if (dtls.dtv[dso_id].beg)
 | 
					  if (dtls.dtv[dso_id].beg) return 0;
 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  uptr tls_size = 0;
 | 
					  uptr tls_size = 0;
 | 
				
			||||||
  uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset;
 | 
					  uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset;
 | 
				
			||||||
  VPrintf(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
 | 
					  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].beg = tls_beg;
 | 
				
			||||||
  dtls.dtv[dso_id].size = tls_size;
 | 
					  dtls.dtv[dso_id].size = tls_size;
 | 
				
			||||||
 | 
					  return dtls.dtv + dso_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DTLS_on_libc_memalign(void *ptr, uptr size) {
 | 
					void DTLS_on_libc_memalign(void *ptr, uptr size) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,9 @@ struct DTLS {
 | 
				
			||||||
  uptr last_memalign_ptr;
 | 
					  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);
 | 
					void DTLS_on_libc_memalign(void *ptr, uptr size);
 | 
				
			||||||
DTLS *DTLS_Get();
 | 
					DTLS *DTLS_Get();
 | 
				
			||||||
void DTLS_Destroy();  // Make sure to call this before the thread is destroyed.
 | 
					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 -g -m64 %s -o %t
 | 
				
			||||||
   RUN: %clang_msan -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
 | 
					   RUN: %clang_msan -g -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
 | 
				
			||||||
   RUN: not %run %t 2>&1 | FileCheck %s
 | 
					   RUN: %run %t 2>&1
 | 
				
			||||||
   CHECK: MemorySanitizer: use-of-uninitialized-value
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   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
 | 
					   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
 | 
					#ifndef BUILD_SO
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue