Index: lsan/lsan.cc =================================================================== --- lsan/lsan.cc +++ lsan/lsan.cc @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#include +#include + #include "lsan.h" #include "sanitizer_common/sanitizer_flags.h" @@ -35,6 +38,38 @@ using namespace __lsan; // NOLINT + +#if SANITIZER_ANDROID +extern "C" { + int __lsan_do_recoverable_leak_check(); +} + + +static void mySigHandler (int sig) { + Printf ("Performing recoverable leak check ...\n"); + int result = __lsan_do_recoverable_leak_check (); + Printf ("Leak result: %d\n", result); +} + + +static void SetSIGHUPHandler() { + sigset_t set; + if (sigfillset (&set) != 0) { + Printf ("Failed to fill signal set\n"); + } + + struct sigaction act; + act.sa_handler = &mySigHandler; + act.sa_mask = set; + act.sa_flags = 0; + + if (sigaction (SIGHUP, &act, NULL) != 0) { + Printf ("Failed to set signal handler\n"); + } +} +#endif // SANITIZER_ANDROID + + static void InitializeFlags() { // Set all the default values. SetCommonFlagsDefaults(); @@ -70,6 +105,12 @@ if (lsan_inited) return; lsan_init_is_running = true; + +#if SANITIZER_ANDROID + EnsureTLSSlotInit(); + SetSIGHUPHandler(); +#endif // SANITIZER_ANDROID + SanitizerToolName = "LeakSanitizer"; CacheBinaryName(); AvoidCVE_2016_2143(); @@ -89,6 +130,10 @@ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); +#if SANITIZER_ANDROID + AndroidLogInit(); +#endif + lsan_inited = true; lsan_init_is_running = false; } Index: lsan/lsan_allocator.h =================================================================== --- lsan/lsan_allocator.h +++ lsan/lsan_allocator.h @@ -18,8 +18,68 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_internal_defs.h" +#include "lsan_common.h" + + +#if SANITIZER_ANDROID +// Voodoo from tsan +#if defined(__aarch64__) +# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; }) +#elif defined(__x86_64__) +# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; }) +#else +#error unsupported architecture +#endif +#endif // SANITIZER_ANDROID + + +static const int TLS_SLOT_TSAN = 8; + + +#define LsanTLSSlotBigStruct ((struct LsanTLSSlotBig*)(__get_tls()[TLS_SLOT_TSAN])) + + namespace __lsan { + +struct ChunkMetadata { + u8 allocated : 8; // Must be first. + ChunkTag tag : 2; + uptr requested_size : 54; + u32 stack_trace_id; +}; + +#if defined(__mips64) || defined(__aarch64__) +static const uptr kMaxAllowedMallocSize = 4UL << 30; +static const uptr kRegionSizeLog = 20; +static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; +typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; +typedef CompactSizeClassMap SizeClassMap; +typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, + sizeof(ChunkMetadata), SizeClassMap, kRegionSizeLog, ByteMap> + PrimaryAllocator; +#else +static const uptr kMaxAllowedMallocSize = 8UL << 30; +static const uptr kAllocatorSpace = 0x600000000000ULL; +static const uptr kAllocatorSize = 0x40000000000ULL; // 4T. +typedef SizeClassAllocator64 PrimaryAllocator; +#endif +typedef SizeClassAllocatorLocalCache AllocatorCache; +typedef LargeMmapAllocator<> SecondaryAllocator; +typedef CombinedAllocator Allocator; + + +#if SANITIZER_ANDROID +struct LsanTLSSlotBig { + int disable_counter_D; + u32 current_thread_tid_D; + AllocatorCache cache_D; +}; +#endif // SANITIZER_ANDROID + + void *Allocate(const StackTrace &stack, uptr size, uptr alignment, bool cleared); void Deallocate(void *p); @@ -34,6 +94,8 @@ void AllocatorThreadFinish(); void InitializeAllocator(); +void EnsureTLSSlotInit(void); + } // namespace __lsan #endif // LSAN_ALLOCATOR_H Index: lsan/lsan_allocator.cc =================================================================== --- lsan/lsan_allocator.cc +++ lsan/lsan_allocator.cc @@ -19,49 +19,48 @@ #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_stacktrace.h" -#include "lsan_common.h" extern "C" void *memset(void *ptr, int value, uptr num); namespace __lsan { -struct ChunkMetadata { - u8 allocated : 8; // Must be first. - ChunkTag tag : 2; - uptr requested_size : 54; - u32 stack_trace_id; -}; -#if defined(__mips64) || defined(__aarch64__) -static const uptr kMaxAllowedMallocSize = 4UL << 30; -static const uptr kRegionSizeLog = 20; -static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; -typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; -typedef CompactSizeClassMap SizeClassMap; -typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, - sizeof(ChunkMetadata), SizeClassMap, kRegionSizeLog, ByteMap> - PrimaryAllocator; -#else -static const uptr kMaxAllowedMallocSize = 8UL << 30; -static const uptr kAllocatorSpace = 0x600000000000ULL; -static const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -typedef SizeClassAllocator64 PrimaryAllocator; -#endif -typedef SizeClassAllocatorLocalCache AllocatorCache; -typedef LargeMmapAllocator<> SecondaryAllocator; -typedef CombinedAllocator Allocator; - static Allocator allocator; +#if !SANITIZER_ANDROID static THREADLOCAL AllocatorCache cache; +#endif // !SANITIZER_ANDROID +#if SANITIZER_ANDROID +void EnsureTLSSlotInit(void) { + if (LsanTLSSlotBigStruct == nullptr) { + struct LsanTLSSlotBig* tlsSlotBigStruct + = (struct LsanTLSSlotBig*) MmapOrDie (sizeof (struct LsanTLSSlotBig), "tlsSlotBigStruct", false); + Printf ("%d calloc'ed tls slot big struct %p (size %d)\n", + GetTid(), tlsSlotBigStruct, sizeof (struct LsanTLSSlotBig)); + + unsigned long i; + for (i = 0; i < sizeof (struct LsanTLSSlotBig); i++) { + ((char*) tlsSlotBigStruct) [i] = 0; + } + + tlsSlotBigStruct->disable_counter_D = 0; // Redundant + tlsSlotBigStruct->current_thread_tid_D = -1; // kInvalidTid; + + __get_tls()[TLS_SLOT_TSAN] = tlsSlotBigStruct; + } +} +#endif // SANITIZER_ANDROID + void InitializeAllocator() { allocator.InitLinkerInitialized(common_flags()->allocator_may_return_null); } void AllocatorThreadFinish() { +#if SANITIZER_ANDROID + allocator.SwallowCache(&(LsanTLSSlotBigStruct->cache_D)); +#else allocator.SwallowCache(&cache); +#endif // SANITIZER_ANDROID } static ChunkMetadata *Metadata(const void *p) { @@ -93,7 +92,11 @@ Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", size); return nullptr; } +#if SANITIZER_ANDROID + void *p = allocator.Allocate(&(LsanTLSSlotBigStruct->cache_D), size, alignment, false); +#else void *p = allocator.Allocate(&cache, size, alignment, false); +#endif // SANITIZER_ANDROID // Do not rely on the allocator to clear the memory (it's slow). if (cleared && allocator.FromPrimary(p)) memset(p, 0, size); @@ -107,7 +110,11 @@ if (&__sanitizer_free_hook) __sanitizer_free_hook(p); RunFreeHooks(p); RegisterDeallocation(p); +#if SANITIZER_ANDROID + allocator.Deallocate(&(LsanTLSSlotBigStruct->cache_D), p); +#else allocator.Deallocate(&cache, p); +#endif // SANITIZER_ANDROID } void *Reallocate(const StackTrace &stack, void *p, uptr new_size, @@ -115,17 +122,30 @@ RegisterDeallocation(p); if (new_size > kMaxAllowedMallocSize) { Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", new_size); +#if SANITIZER_ANDROID + allocator.Deallocate(&(LsanTLSSlotBigStruct->cache_D), p); +#else allocator.Deallocate(&cache, p); +#endif // SANITIZER_ANDROID return nullptr; } +#if SANITIZER_ANDROID + p = allocator.Reallocate(&(LsanTLSSlotBigStruct->cache_D), p, new_size, alignment); +#else p = allocator.Reallocate(&cache, p, new_size, alignment); +#endif // SANITIZER_ANDROID RegisterAllocation(stack, p, new_size); return p; } void GetAllocatorCacheRange(uptr *begin, uptr *end) { +#if SANITIZER_ANDROID + *begin = (uptr)&(LsanTLSSlotBigStruct->cache_D); + *end = *begin + sizeof(LsanTLSSlotBigStruct->cache_D); +#else *begin = (uptr)&cache; *end = *begin + sizeof(cache); +#endif // SANITIZER_ANDROID } uptr GetMallocUsableSize(const void *p) { Index: lsan/lsan_common.h =================================================================== --- lsan/lsan_common.h +++ lsan/lsan_common.h @@ -22,7 +22,7 @@ #include "sanitizer_common/sanitizer_stoptheworld.h" #include "sanitizer_common/sanitizer_symbolizer.h" -#if (SANITIZER_LINUX && !SANITIZER_ANDROID) && (SANITIZER_WORDSIZE == 64) \ +#if (SANITIZER_LINUX) && (SANITIZER_WORDSIZE == 64) \ && (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__)) #define CAN_SANITIZE_LEAKS 1 #else Index: lsan/lsan_common.cc =================================================================== --- lsan/lsan_common.cc +++ lsan/lsan_common.cc @@ -14,6 +14,8 @@ #include "lsan_common.h" +#include "lsan_allocator.h" + #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" @@ -32,7 +34,19 @@ // also to protect the global list of root regions. BlockingMutex global_mutex(LINKER_INITIALIZED); +#if SANITIZER_ANDROID THREADLOCAL int disable_counter; +bool DisabledInThisThread() { return LsanTLSSlotBigStruct->disable_counter_D > 0; } +void DisableInThisThread() { LsanTLSSlotBigStruct->disable_counter_D++; } +void EnableInThisThread() { + if (!LsanTLSSlotBigStruct->disable_counter_D && common_flags()->detect_leaks) { + Report("Unmatched call to __lsan_enable().\n"); + Die(); + } + LsanTLSSlotBigStruct->disable_counter_D--; +} +#else +THREADLOCAL int disable_counter; bool DisabledInThisThread() { return disable_counter > 0; } void DisableInThisThread() { disable_counter++; } void EnableInThisThread() { @@ -42,7 +56,9 @@ } disable_counter--; } +#endif // SANITIZER_ANDROID + Flags lsan_flags; void Flags::SetDefaults() { Index: lsan/lsan_flags.inc =================================================================== --- lsan/lsan_flags.inc +++ lsan/lsan_flags.inc @@ -30,8 +30,13 @@ "Root set: include global variables (.data and .bss)") LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks") LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers") +#if SANITIZER_ANDROID +LSAN_FLAG(bool, use_tls, false, + "Root set: include TLS and thread-specific storage") +#else LSAN_FLAG(bool, use_tls, true, "Root set: include TLS and thread-specific storage") +#endif // SANITIZER_ANDROID LSAN_FLAG(bool, use_root_regions, true, "Root set: include regions added via __lsan_register_root_region().") LSAN_FLAG(bool, use_ld_allocations, true, Index: lsan/lsan_thread.cc =================================================================== --- lsan/lsan_thread.cc +++ lsan/lsan_thread.cc @@ -25,7 +25,9 @@ const u32 kInvalidTid = (u32) -1; static ThreadRegistry *thread_registry; +#if !SANITIZER_ANDROID static THREADLOCAL u32 current_thread_tid = kInvalidTid; +#endif // SANITIZER_ANDROID static ThreadContextBase *CreateThreadContext(u32 tid) { void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); @@ -42,11 +44,21 @@ } u32 GetCurrentThread() { +#if SANITIZER_ANDROID + return LsanTLSSlotBigStruct->current_thread_tid_D; +#else return current_thread_tid; +#endif // SANITIZER_ANDROID } void SetCurrentThread(u32 tid) { +#if SANITIZER_ANDROID + EnsureTLSSlotInit(); + + LsanTLSSlotBigStruct->current_thread_tid_D = tid; +#else current_thread_tid = tid; +#endif // SANITIZER_ANDROID } ThreadContext::ThreadContext(int tid) Index: msan/msan.h =================================================================== --- msan/msan.h +++ msan/msan.h @@ -22,10 +22,18 @@ #include "msan_flags.h" #include "ubsan/ubsan_platform.h" +#if SANITIZER_ANDROID +#include "msan_thread.h" +#endif // SANITIZER_ANDROID + #ifndef MSAN_REPLACE_OPERATORS_NEW_AND_DELETE # define MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 1 #endif +#if SANITIZER_ANDROID +#define MSAN_CONTAINS_UBSAN 0 +#endif // SANITIZER_ANDROID + #ifndef MSAN_CONTAINS_UBSAN # define MSAN_CONTAINS_UBSAN CAN_SANITIZE_UB #endif @@ -216,6 +224,61 @@ const int kMsanParamTlsSize = 800; const int kMsanRetvalTlsSize = 800; +#if SANITIZER_ANDROID + +// Voodoo from tsan +#if defined(__aarch64__) +# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; }) +#elif defined(__x86_64__) +# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; }) +#else +#error unsupported architecture +#endif + +static const int TLS_SLOT_TSAN = 8; + + +struct MsanTLSSlot { + int dummy; + + __msan::MsanThread* thread_D; + + int in_interceptor_scope_D; + int is_in_symbolizer_D; + + int msan_expect_umr_D = 0; + int msan_expected_umr_found_D = 0; + + SANITIZER_INTERFACE_ATTRIBUTE + u64 __msan_param_tls_D[kMsanParamTlsSize / sizeof(u64)]; + + SANITIZER_INTERFACE_ATTRIBUTE + u32 __msan_param_origin_tls_D[kMsanParamTlsSize / sizeof(u32)]; + + SANITIZER_INTERFACE_ATTRIBUTE + u64 __msan_retval_tls_D[kMsanRetvalTlsSize / sizeof(u64)]; + + SANITIZER_INTERFACE_ATTRIBUTE + u32 __msan_retval_origin_tls_D; + + SANITIZER_INTERFACE_ATTRIBUTE + ALIGNED(16) u64 __msan_va_arg_tls_D[kMsanParamTlsSize / sizeof(u64)]; + + SANITIZER_INTERFACE_ATTRIBUTE + u64 __msan_va_arg_overflow_size_tls_D; + + SANITIZER_INTERFACE_ATTRIBUTE + u32 __msan_origin_tls_D; +}; + + +#define MsanTLSSlotStruct ((struct MsanTLSSlot*)(__get_tls()[TLS_SLOT_TSAN])) + + +void EnsureTLSSlotInit(void); +#endif // SANITIZER_ANDROID + + namespace __msan { extern int msan_inited; extern bool msan_init_is_running; Index: msan/msan.cc =================================================================== --- msan/msan.cc +++ msan/msan.cc @@ -33,6 +33,7 @@ using namespace __sanitizer; +#if !SANITIZER_ANDROID // Globals. static THREADLOCAL int msan_expect_umr = 0; static THREADLOCAL int msan_expected_umr_found = 0; @@ -64,6 +65,7 @@ THREADLOCAL u32 __msan_origin_tls; static THREADLOCAL int is_in_symbolizer; +#endif // SANITIZER_ANDROID extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; @@ -75,9 +77,15 @@ namespace __msan { +#if SANITIZER_ANDROID +void EnterSymbolizer() { ++(MsanTLSSlotStruct->is_in_symbolizer_D); } +void ExitSymbolizer() { --(MsanTLSSlotStruct->is_in_symbolizer_D); } +bool IsInSymbolizer() { return MsanTLSSlotStruct->is_in_symbolizer_D; } +#else void EnterSymbolizer() { ++is_in_symbolizer; } void ExitSymbolizer() { --is_in_symbolizer; } bool IsInSymbolizer() { return is_in_symbolizer; } +#endif // SANITIZER_ANDROID static Flags msan_flags; @@ -230,10 +238,22 @@ } void PrintWarning(uptr pc, uptr bp) { +#if SANITIZER_ANDROID + PrintWarningWithOrigin(pc, bp, MsanTLSSlotStruct->__msan_origin_tls_D); +#else PrintWarningWithOrigin(pc, bp, __msan_origin_tls); +#endif // SANITIZER_ANDROID } void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) { +#if SANITIZER_ANDROID + if (MsanTLSSlotStruct->msan_expect_umr_D) { + // Printf("Expected UMR\n"); + MsanTLSSlotStruct->__msan_origin_tls_D = origin; + MsanTLSSlotStruct->msan_expected_umr_found_D = 1; + return; + } +#else if (msan_expect_umr) { // Printf("Expected UMR\n"); __msan_origin_tls = origin; @@ -240,6 +260,7 @@ msan_expected_umr_found = 1; return; } +#endif // SANITIZER_ANDROID ++msan_report_count; @@ -258,14 +279,43 @@ } void UnpoisonParam(uptr n) { +#if SANITIZER_ANDROID + internal_memset(MsanTLSSlotStruct->__msan_param_tls_D, 0, n * sizeof(*MsanTLSSlotStruct->__msan_param_tls_D)); +#else internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls)); +#endif // SANITIZER_ANDROID } +#if SANITIZER_ANDROID // Backup MSan runtime TLS state. // Implementation must be async-signal-safe. // Instances of this class may live on the signal handler stack, and data size // may be an issue. void ScopedThreadLocalStateBackup::Backup() { + va_arg_overflow_size_tls = MsanTLSSlotStruct->__msan_va_arg_overflow_size_tls_D; +} + +void ScopedThreadLocalStateBackup::Restore() { + // A lame implementation that only keeps essential state and resets the rest. + MsanTLSSlotStruct->__msan_va_arg_overflow_size_tls_D = va_arg_overflow_size_tls; + + internal_memset(MsanTLSSlotStruct->__msan_param_tls_D, 0, sizeof(MsanTLSSlotStruct->__msan_param_tls_D)); + internal_memset(MsanTLSSlotStruct->__msan_retval_tls_D, 0, sizeof(MsanTLSSlotStruct->__msan_retval_tls_D)); + internal_memset(MsanTLSSlotStruct->__msan_va_arg_tls_D, 0, sizeof(MsanTLSSlotStruct->__msan_va_arg_tls_D)); + + if (__msan_get_track_origins()) { + internal_memset(&MsanTLSSlotStruct->__msan_retval_origin_tls_D, 0, + sizeof(MsanTLSSlotStruct->__msan_retval_origin_tls_D)); + internal_memset(MsanTLSSlotStruct->__msan_param_origin_tls_D, 0, + sizeof(MsanTLSSlotStruct->__msan_param_origin_tls_D)); + } +} +#else +// Backup MSan runtime TLS state. +// Implementation must be async-signal-safe. +// Instances of this class may live on the signal handler stack, and data size +// may be an issue. +void ScopedThreadLocalStateBackup::Backup() { va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls; } @@ -284,6 +334,7 @@ sizeof(__msan_param_origin_tls)); } } +#endif // SANITIZER_ANDROID void UnpoisonThreadLocalState() { } @@ -369,6 +420,51 @@ Die(); } +#if SANITIZER_ANDROID +u64* get__msan_param_tls0(void) { + return &(MsanTLSSlotStruct->__msan_param_tls_D [0]); +} + +u32* get__msan_param_origin_tls0(void) { + return &(MsanTLSSlotStruct->__msan_param_origin_tls_D [0]); +} + +u64* get__msan_retval_tls0(void) { + return &(MsanTLSSlotStruct->__msan_retval_tls_D [0]); +} + +u32* get__msan_retval_origin_tls0(void) { + return &(MsanTLSSlotStruct->__msan_retval_origin_tls_D); +} + +u64* get__msan_va_arg_tls0(void) { + return &(MsanTLSSlotStruct->__msan_va_arg_tls_D [0]); +} + +u64* get__msan_va_arg_overflow_size_tls0(void) { + return &(MsanTLSSlotStruct->__msan_va_arg_overflow_size_tls_D); +} + +u32* get__msan_origin_tls0(void) { + return &(MsanTLSSlotStruct->__msan_origin_tls_D); +} + +void EnsureTLSSlotInit(void) { + if (__get_tls()[TLS_SLOT_TSAN] == nullptr) { + struct MsanTLSSlot* slot \ + = (struct MsanTLSSlot*)MmapOrDie(sizeof (struct MsanTLSSlot), __func__); + CHECK_NE (slot, nullptr); + slot->dummy = 42; + slot->in_interceptor_scope_D = 0; + slot->is_in_symbolizer_D = 0; + slot->thread_D = nullptr; + + __get_tls()[TLS_SLOT_TSAN] = slot; + VPrintf (0, "[EnsureTLSSlotInit] blah is at %p\n", slot); + } +} +#endif // SANITIZER_ANDROID + void __msan_init() { CHECK(!msan_init_is_running); if (msan_inited) return; @@ -375,6 +471,10 @@ msan_init_is_running = 1; SanitizerToolName = "MemorySanitizer"; +#if SANITIZER_ANDROID + EnsureTLSSlotInit(); +#endif // SANITIZER_ANDROID + AvoidCVE_2016_2143(); InitTlsSize(); @@ -426,6 +526,10 @@ VPrintf(1, "MemorySanitizer init done\n"); +#if SANITIZER_ANDROID + AndroidLogInit(); +#endif + msan_init_is_running = 0; msan_inited = 1; } @@ -436,8 +540,13 @@ void __msan_set_expect_umr(int expect_umr) { if (expect_umr) { +#if SANITIZER_ANDROID + MsanTLSSlotStruct->msan_expected_umr_found_D = 0; + } else if (!MsanTLSSlotStruct->msan_expected_umr_found_D) { +#else msan_expected_umr_found = 0; } else if (!msan_expected_umr_found) { +#endif // SANITIZER_ANDROID GET_CALLER_PC_BP_SP; (void)sp; GET_FATAL_STACK_TRACE_PC_BP(pc, bp); @@ -444,7 +553,11 @@ ReportExpectedUMRNotFound(&stack); Die(); } +#if SANITIZER_ANDROID + MsanTLSSlotStruct->msan_expect_umr_D = expect_umr; +#else msan_expect_umr = expect_umr; +#endif // SANITIZER_ANDROID } void __msan_print_shadow(const void *x, uptr size) { @@ -504,7 +617,11 @@ NOINLINE void __msan_clear_on_return() { +#if SANITIZER_ANDROID + MsanTLSSlotStruct->__msan_param_tls_D[0] = 0; +#else __msan_param_tls[0] = 0; +#endif // SANITIZER_ANDROID } void __msan_partial_poison(const void* data, void* shadow, uptr size) { @@ -578,7 +695,55 @@ return o.raw_id() == prev_id; } +#if SANITIZER_ANDROID u32 __msan_get_umr_origin() { + return MsanTLSSlotStruct->__msan_origin_tls_D; +} + +u16 __sanitizer_unaligned_load16(const uu16 *p) { + MsanTLSSlotStruct->__msan_retval_tls_D[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); + if (__msan_get_track_origins()) + MsanTLSSlotStruct->__msan_retval_origin_tls_D = GetOriginIfPoisoned((uptr)p, sizeof(*p)); + return *p; +} +u32 __sanitizer_unaligned_load32(const uu32 *p) { + MsanTLSSlotStruct->__msan_retval_tls_D[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); + if (__msan_get_track_origins()) + MsanTLSSlotStruct->__msan_retval_origin_tls_D = GetOriginIfPoisoned((uptr)p, sizeof(*p)); + return *p; +} +u64 __sanitizer_unaligned_load64(const uu64 *p) { + MsanTLSSlotStruct->__msan_retval_tls_D[0] = *(uu64 *)MEM_TO_SHADOW((uptr)p); + if (__msan_get_track_origins()) + MsanTLSSlotStruct->__msan_retval_origin_tls_D = GetOriginIfPoisoned((uptr)p, sizeof(*p)); + return *p; +} +void __sanitizer_unaligned_store16(uu16 *p, u16 x) { + u16 s = MsanTLSSlotStruct->__msan_param_tls_D[1]; + *(uu16 *)MEM_TO_SHADOW((uptr)p) = s; + if (s && __msan_get_track_origins()) + if (uu32 o = MsanTLSSlotStruct->__msan_param_origin_tls_D[2]) + SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); + *p = x; +} +void __sanitizer_unaligned_store32(uu32 *p, u32 x) { + u32 s = MsanTLSSlotStruct->__msan_param_tls_D[1]; + *(uu32 *)MEM_TO_SHADOW((uptr)p) = s; + if (s && __msan_get_track_origins()) + if (uu32 o = MsanTLSSlotStruct->__msan_param_origin_tls_D[2]) + SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); + *p = x; +} +void __sanitizer_unaligned_store64(uu64 *p, u64 x) { + u64 s = MsanTLSSlotStruct->__msan_param_tls_D[1]; + *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; + if (s && __msan_get_track_origins()) + if (uu32 o = MsanTLSSlotStruct->__msan_param_origin_tls_D[2]) + SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); + *p = x; +} +#else +u32 __msan_get_umr_origin() { return __msan_origin_tls; } @@ -624,7 +789,9 @@ SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); *p = x; } +#endif // SANITIZER_ANDROID + void __msan_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } Index: msan/msan_flags.inc =================================================================== --- msan/msan_flags.inc +++ msan/msan_flags.inc @@ -29,7 +29,11 @@ MSAN_FLAG(bool, report_umrs, true, "") MSAN_FLAG(bool, wrap_signals, true, "") MSAN_FLAG(bool, print_stats, false, "") +#if SANITIZER_ANDROID +MSAN_FLAG(bool, halt_on_error, false, "") +#else MSAN_FLAG(bool, halt_on_error, !&__msan_keep_going, "") +#endif // SANITIZER_ANDROID MSAN_FLAG(bool, atexit, false, "") MSAN_FLAG(int, store_context_size, 20, "Like malloc_context_size, but for uninit stores.") Index: msan/msan_interceptors.cc =================================================================== --- msan/msan_interceptors.cc +++ msan/msan_interceptors.cc @@ -50,6 +50,29 @@ #define __errno_location __error #endif +#if SANITIZER_ANDROID +// From bionic/libc/include/errno.h: +// "internal function returning the address of the thread-specific errno" +extern "C" volatile int* __errno(void); +#define __errno_location (int*)__errno + + +struct InterceptorScope { + InterceptorScope() { + EnsureTLSSlotInit(); + ++(MsanTLSSlotStruct->in_interceptor_scope_D); + } + + ~InterceptorScope() { + --(MsanTLSSlotStruct->in_interceptor_scope_D); + } +}; + +bool IsInInterceptorScope() { + EnsureTLSSlotInit(); + return MsanTLSSlotStruct->in_interceptor_scope_D; +} +#else // True if this is a nested interceptor. static THREADLOCAL int in_interceptor_scope; @@ -63,6 +86,7 @@ bool IsInInterceptorScope() { return in_interceptor_scope; } +#endif // SANITIZER_ANDROID #define ENSURE_MSAN_INITED() do { \ CHECK(!msan_init_is_running); \ @@ -1104,6 +1128,10 @@ extern "C" int pthread_attr_destroy(void *attr); static void *MsanThreadStartFunc(void *arg) { +#if SANITIZER_ANDROID + EnsureTLSSlotInit(); +#endif // SANITIZER_ANDROID + MsanThread *t = (MsanThread *)arg; SetCurrentThread(t); return t->ThreadStart(); @@ -1188,6 +1216,7 @@ DECLARE_REAL(int, shmctl, int shmid, int cmd, void *buf) +#if !SANITIZER_ANDROID INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) { ENSURE_MSAN_INITED(); void *p = REAL(shmat)(shmid, shmaddr, shmflg); @@ -1200,6 +1229,10 @@ } return p; } +#define MSAN_MAYBE_INTERCEPT_SHMAT INTERCEPT_FUNCTION(shmat) +#else +#define MSAN_MAYBE_INTERCEPT_SHMAT +#endif // !SANITIZER_ANDROID static void BeforeFork() { StackDepotLockAll(); @@ -1346,6 +1379,7 @@ #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s) #include "sanitizer_common/sanitizer_common_syscalls.inc" +#if !SANITIZER_ANDROID struct dlinfo { char *dli_fname; void *dli_fbase; @@ -1405,6 +1439,7 @@ int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); return res; } +#endif // !SANITIZER_ANDROID // These interface functions reside here so that they can use // REAL(memset), etc. @@ -1566,9 +1601,11 @@ INTERCEPT_FUNCTION(gethostname); MSAN_MAYBE_INTERCEPT_EPOLL_WAIT; MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT; +#if !SANITIZER_ANDROID INTERCEPT_FUNCTION(dladdr); INTERCEPT_FUNCTION(dlerror); INTERCEPT_FUNCTION(dl_iterate_phdr); +#endif // !SANITIZER_ANDROID INTERCEPT_FUNCTION(getrusage); INTERCEPT_FUNCTION(sigaction); INTERCEPT_FUNCTION(signal); @@ -1581,7 +1618,7 @@ INTERCEPT_FUNCTION(pthread_join); INTERCEPT_FUNCTION(tzset); INTERCEPT_FUNCTION(__cxa_atexit); - INTERCEPT_FUNCTION(shmat); + MSAN_MAYBE_INTERCEPT_SHMAT; INTERCEPT_FUNCTION(fork); INTERCEPT_FUNCTION(openpty); INTERCEPT_FUNCTION(forkpty); Index: msan/msan_interface_internal.h =================================================================== --- msan/msan_interface_internal.h +++ msan/msan_interface_internal.h @@ -164,6 +164,30 @@ SANITIZER_INTERFACE_ATTRIBUTE void __msan_copy_shadow(void *dst, const void *src, uptr size); + +#if SANITIZER_ANDROID +SANITIZER_INTERFACE_ATTRIBUTE +u64* get__msan_param_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u32* get__msan_param_origin_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u64* get__msan_retval_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u32* get__msan_retval_origin_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u64* get__msan_va_arg_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u64* get__msan_va_arg_overflow_size_tls0(void); + +SANITIZER_INTERFACE_ATTRIBUTE +u32* get__msan_origin_tls0(void); +#endif // SANITIZER_ANDROID + } // extern "C" #endif // MSAN_INTERFACE_INTERNAL_H Index: msan/msan_linux.cc =================================================================== --- msan/msan_linux.cc +++ msan/msan_linux.cc @@ -26,7 +26,11 @@ #include #include #include + +#if !SANITIZER_ANDROID #include +#endif // !SANITIZER_ANDROID + #include #include @@ -173,28 +177,46 @@ // ---------------------- TSD ---------------- {{{1 +#if !SANITIZER_ANDROID static pthread_key_t tsd_key; +#endif // !SANITIZER_ANDROID static bool tsd_key_inited = false; void MsanTSDInit(void (*destructor)(void *tsd)) { CHECK(!tsd_key_inited); tsd_key_inited = true; +#if !SANITIZER_ANDROID CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); +#endif // SANITIZER_ANDROID } +#if !SANITIZER_ANDROID static THREADLOCAL MsanThread* msan_current_thread; +#endif // SANITIZER_ANDROID MsanThread *GetCurrentThread() { +#if SANITIZER_ANDROID + return MsanTLSSlotStruct->thread_D; +#else return msan_current_thread; +#endif // SANITIZER_ANDROID } void SetCurrentThread(MsanThread *t) { // Make sure we do not reset the current MsanThread. +#if SANITIZER_ANDROID + CHECK_EQ(0, MsanTLSSlotStruct->thread_D); + MsanTLSSlotStruct->thread_D = t; +#else CHECK_EQ(0, msan_current_thread); msan_current_thread = t; +#endif // SANITIZER_ANDROID // Make sure that MsanTSDDtor gets called at the end. CHECK(tsd_key_inited); + +#if !SANITIZER_ANDROID pthread_setspecific(tsd_key, (void *)t); +#endif // !SANITIZER_ANDROID } void MsanTSDDtor(void *tsd) { @@ -201,10 +223,16 @@ MsanThread *t = (MsanThread*)tsd; if (t->destructor_iterations_ > 1) { t->destructor_iterations_--; +#if !SANITIZER_ANDROID CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); +#endif // SANITIZER_ANDROID return; } +#if SANITIZER_ANDROID + MsanTLSSlotStruct->thread_D = nullptr; +#else msan_current_thread = nullptr; +#endif // SANITIZER_ANDROID // Make sure that signal handler can not see a stale current thread pointer. atomic_signal_fence(memory_order_seq_cst); MsanThread::TSDDtor(tsd); Index: msan/msan_poisoning.cc =================================================================== --- msan/msan_poisoning.cc +++ msan/msan_poisoning.cc @@ -120,6 +120,12 @@ } void SetShadow(const void *ptr, uptr size, u8 value) { +#if SANITIZER_ANDROID + if (msan_init_is_running || (!msan_inited)) { + return; + } +#endif + uptr PageSize = GetPageSizeCached(); uptr shadow_beg = MEM_TO_SHADOW(ptr); uptr shadow_end = shadow_beg + size; Index: msan/msan_thread.cc =================================================================== --- msan/msan_thread.cc +++ msan/msan_thread.cc @@ -35,10 +35,12 @@ __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_); if (tls_begin_ != tls_end_) __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_); +#if !SANITIZER_ANDROID DTLS *dtls = DTLS_Get(); CHECK_NE(dtls, 0); for (uptr i = 0; i < dtls->dtv_size; ++i) __msan_unpoison((void *)(dtls->dtv[i].beg), dtls->dtv[i].size); +#endif // !SANITIZER_ANDROID } void MsanThread::Init() { Index: sanitizer_common/sanitizer_platform_limits_posix.h =================================================================== --- sanitizer_common/sanitizer_platform_limits_posix.h +++ sanitizer_common/sanitizer_platform_limits_posix.h @@ -53,9 +53,10 @@ #if !SANITIZER_ANDROID extern unsigned struct_statfs_sz; extern unsigned struct_sockaddr_sz; - extern unsigned ucontext_t_sz; #endif // !SANITIZER_ANDROID + extern unsigned ucontext_t_sz; + #if SANITIZER_LINUX #if defined(__x86_64__) @@ -172,6 +173,8 @@ struct __sanitizer_mallinfo { uptr v[10]; }; + + extern unsigned struct_rlimit64_sz; #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID Index: sanitizer_common/sanitizer_platform_limits_posix.cc =================================================================== --- sanitizer_common/sanitizer_platform_limits_posix.cc +++ sanitizer_common/sanitizer_platform_limits_posix.cc @@ -233,6 +233,9 @@ unsigned struct_statfs_sz = sizeof(struct statfs); unsigned struct_sockaddr_sz = sizeof(struct sockaddr); unsigned ucontext_t_sz = sizeof(ucontext_t); +#else + // Needed by msan for SignalAction() + unsigned ucontext_t_sz = sizeof(ucontext_t); #endif // !SANITIZER_ANDROID #if SANITIZER_LINUX @@ -259,6 +262,11 @@ unsigned struct_statvfs64_sz = sizeof(struct statvfs64); #endif // SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_ANDROID + // Needed by msan for getrlimit64() + unsigned struct_rlimit64_sz = sizeof(struct rlimit64); +#endif // SANITIZER_ANDROID + #if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID unsigned struct_timex_sz = sizeof(struct timex); unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);