diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:53 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:53 +0000 |
commit | 4658ff5fee0369e08fe69bce90019fad154d9330 (patch) | |
tree | 5ac9da286baff9e296c083f060fc58b2e53b63bf /lib | |
parent | 7edd24de96f22ad70fd3ca16a3c51723383cd58b (diff) |
Notes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_allocator.cc | 21 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator_combined.h | 19 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator_secondary.h | 7 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 3 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_flags.inc | 3 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux.cc | 9 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 1 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_mac.cc | 15 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_posix.cc | 16 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_win.cc | 10 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_report.cc | 8 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_sync.h | 2 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 10 | ||||
-rw-r--r-- | lib/ubsan/ubsan_type_hash_itanium.cc | 4 |
14 files changed, 93 insertions, 35 deletions
diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index 7010b60236141..1ded7794c9f4b 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -235,6 +235,8 @@ struct Allocator { AllocatorCache fallback_allocator_cache; QuarantineCache fallback_quarantine_cache; + atomic_uint8_t rss_limit_exceeded; + // ------------------- Options -------------------------- atomic_uint16_t min_redzone; atomic_uint16_t max_redzone; @@ -268,6 +270,14 @@ struct Allocator { SharedInitCode(options); } + bool RssLimitExceeded() { + return atomic_load(&rss_limit_exceeded, memory_order_relaxed); + } + + void SetRssLimitExceeded(bool limit_exceeded) { + atomic_store(&rss_limit_exceeded, limit_exceeded, memory_order_relaxed); + } + void RePoisonChunk(uptr chunk) { // This could be a user-facing chunk (with redzones), or some internal // housekeeping chunk, like TransferBatch. Start by assuming the former. @@ -363,6 +373,8 @@ struct Allocator { AllocType alloc_type, bool can_fill) { if (UNLIKELY(!asan_inited)) AsanInitFromRtl(); + if (RssLimitExceeded()) + return allocator.ReturnNullOrDieOnOOM(); Flags &fl = *flags(); CHECK(stack); const uptr min_alignment = SHADOW_GRANULARITY; @@ -400,16 +412,15 @@ struct Allocator { AsanThread *t = GetCurrentThread(); void *allocated; - bool check_rss_limit = true; if (t) { AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); allocated = - allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); + allocator.Allocate(cache, needed_size, 8, false); } else { SpinMutexLock l(&fallback_mutex); AllocatorCache *cache = &fallback_allocator_cache; allocated = - allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); + allocator.Allocate(cache, needed_size, 8, false); } if (!allocated) return allocator.ReturnNullOrDieOnOOM(); @@ -866,8 +877,8 @@ void asan_mz_force_unlock() { instance.ForceUnlock(); } -void AsanSoftRssLimitExceededCallback(bool exceeded) { - instance.allocator.SetRssLimitIsExceeded(exceeded); +void AsanSoftRssLimitExceededCallback(bool limit_exceeded) { + instance.SetRssLimitExceeded(limit_exceeded); } } // namespace __asan diff --git a/lib/sanitizer_common/sanitizer_allocator_combined.h b/lib/sanitizer_common/sanitizer_allocator_combined.h index 19e1ae9b9f753..2c2390b3d2c6e 100644 --- a/lib/sanitizer_common/sanitizer_allocator_combined.h +++ b/lib/sanitizer_common/sanitizer_allocator_combined.h @@ -43,12 +43,12 @@ class CombinedAllocator { } void *Allocate(AllocatorCache *cache, uptr size, uptr alignment, - bool cleared = false, bool check_rss_limit = false) { + bool cleared = false) { // Returning 0 on malloc(0) may break a lot of code. if (size == 0) size = 1; - if (size + alignment < size) return ReturnNullOrDieOnBadRequest(); - if (check_rss_limit && RssLimitIsExceeded()) return ReturnNullOrDieOnOOM(); + if (size + alignment < size) + return ReturnNullOrDieOnBadRequest(); uptr original_size = size; // If alignment requirements are to be fulfilled by the frontend allocator // rather than by the primary or secondary, passing an alignment lower than @@ -89,7 +89,8 @@ class CombinedAllocator { } void *ReturnNullOrDieOnOOM() { - if (MayReturnNull()) return nullptr; + if (MayReturnNull()) + return nullptr; ReportAllocatorCannotReturnNull(true); } @@ -106,15 +107,6 @@ class CombinedAllocator { primary_.SetReleaseToOSIntervalMs(release_to_os_interval_ms); } - bool RssLimitIsExceeded() { - return atomic_load(&rss_limit_is_exceeded_, memory_order_acquire); - } - - void SetRssLimitIsExceeded(bool rss_limit_is_exceeded) { - atomic_store(&rss_limit_is_exceeded_, rss_limit_is_exceeded, - memory_order_release); - } - void Deallocate(AllocatorCache *cache, void *p) { if (!p) return; if (primary_.PointerIsMine(p)) @@ -228,6 +220,5 @@ class CombinedAllocator { SecondaryAllocator secondary_; AllocatorGlobalStats stats_; atomic_uint8_t may_return_null_; - atomic_uint8_t rss_limit_is_exceeded_; }; diff --git a/lib/sanitizer_common/sanitizer_allocator_secondary.h b/lib/sanitizer_common/sanitizer_allocator_secondary.h index 2e98e591b4321..2c69f47ec4e68 100644 --- a/lib/sanitizer_common/sanitizer_allocator_secondary.h +++ b/lib/sanitizer_common/sanitizer_allocator_secondary.h @@ -36,9 +36,12 @@ class LargeMmapAllocator { if (alignment > page_size_) map_size += alignment; // Overflow. - if (map_size < size) return ReturnNullOrDieOnBadRequest(); + if (map_size < size) + return ReturnNullOrDieOnBadRequest(); uptr map_beg = reinterpret_cast<uptr>( - MmapOrDie(map_size, "LargeMmapAllocator")); + MmapOrDieOnFatalError(map_size, "LargeMmapAllocator")); + if (!map_beg) + return ReturnNullOrDieOnOOM(); CHECK(IsAligned(map_beg, page_size_)); MapUnmapCallback().OnMap(map_beg, map_size); uptr map_end = map_beg + map_size; diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 79ee6873bcc44..875a46009f494 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -85,6 +85,9 @@ INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) { return MmapOrDie(size, mem_type, /*raw_report*/ true); } void UnmapOrDie(void *addr, uptr size); +// Behaves just like MmapOrDie, but tolerates out of memory condition, in that +// case returns nullptr. +void *MmapOrDieOnFatalError(uptr size, const char *mem_type); void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr); void *MmapNoReserveOrDie(uptr size, const char *mem_type); diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 8c486b5b1b4db..9f71861efcdb2 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -93,6 +93,9 @@ COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo, COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes, COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE)) #undef COMMON_FLAG_HANDLE_SIGNAL_HELP +COMMON_FLAG(bool, allow_user_segv_handler, true, + "Deprecated. True has no effect, use handle_sigbus=1. If false, " + "handle_*=1 will be upgraded to handle_*=2.") COMMON_FLAG(bool, use_sigaltstack, true, "If set, uses alternate stack for signal handling.") COMMON_FLAG(bool, detect_deadlocks, false, diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index cec2f264cbc4f..d31c49d694aef 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -1396,7 +1396,7 @@ AndroidApiLevel AndroidGetApiLevel() { #endif -HandleSignalMode GetHandleSignalMode(int signum) { +static HandleSignalMode GetHandleSignalModeImpl(int signum) { switch (signum) { case SIGABRT: return common_flags()->handle_abort; @@ -1412,6 +1412,13 @@ HandleSignalMode GetHandleSignalMode(int signum) { return kHandleSignalNo; } +HandleSignalMode GetHandleSignalMode(int signum) { + HandleSignalMode result = GetHandleSignalModeImpl(signum); + if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) + return kHandleSignalExclusive; + return result; +} + #if !SANITIZER_GO void *internal_start_thread(void(*func)(void *arg), void *arg) { // Start the thread with signals blocked, otherwise it can steal user signals. diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index a15b5858af409..894013ddd8806 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -113,7 +113,6 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, my_pthread_attr_getstack(&attr, &stackaddr, &stacksize); pthread_attr_destroy(&attr); - CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check. *stack_top = (uptr)stackaddr + stacksize; *stack_bottom = (uptr)stackaddr; } diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index f1b9e5fda5c0e..a788a091592f9 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -414,10 +414,7 @@ void ListOfModules::init() { memory_mapping.DumpListOfModules(&modules_); } -HandleSignalMode GetHandleSignalMode(int signum) { - // Handling fatal signals on watchOS and tvOS devices is disallowed. - if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) - return kHandleSignalNo; +static HandleSignalMode GetHandleSignalModeImpl(int signum) { switch (signum) { case SIGABRT: return common_flags()->handle_abort; @@ -433,6 +430,16 @@ HandleSignalMode GetHandleSignalMode(int signum) { return kHandleSignalNo; } +HandleSignalMode GetHandleSignalMode(int signum) { + // Handling fatal signals on watchOS and tvOS devices is disallowed. + if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) + return kHandleSignalNo; + HandleSignalMode result = GetHandleSignalModeImpl(signum); + if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) + return kHandleSignalExclusive; + return result; +} + MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; MacosVersion GetMacosVersionInternal() { diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index 9916f4d385384..4184a84c73f83 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -22,6 +22,7 @@ #include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" +#include <errno.h> #include <fcntl.h> #include <signal.h> #include <sys/mman.h> @@ -145,6 +146,21 @@ void UnmapOrDie(void *addr, uptr size) { DecreaseTotalMmap(size); } +void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { + size = RoundUpTo(size, GetPageSizeCached()); + uptr res = internal_mmap(nullptr, size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + int reserrno; + if (internal_iserror(res, &reserrno)) { + if (reserrno == ENOMEM) + return nullptr; + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); + } + IncreaseTotalMmap(size); + return (void *)res; +} + // We want to map a chunk of address space aligned to 'alignment'. // We do it by maping a bit more and then unmaping redundant pieces. // We probably can do it with fewer syscalls in some OS-dependent way. diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index afc3bb0ac6784..506e7374a3298 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -131,6 +131,16 @@ void UnmapOrDie(void *addr, uptr size) { } } +void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { + void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (rv == 0) { + error_t last_error = GetLastError(); + if (last_error != ERROR_NOT_ENOUGH_MEMORY) + ReportMmapFailureAndDie(size, mem_type, "allocate", last_error); + } + return rv; +} + // We want to map a chunk of address space aligned to 'alignment'. void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { CHECK(IsPowerOfTwo(size)); diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 2de7ffc746fd2..32cc3325fe40f 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -92,7 +92,8 @@ static const char *ReportTypeString(ReportType typ, uptr tag) { if (typ == ReportTypeVptrUseAfterFree) return "heap-use-after-free (virtual call vs free)"; if (typ == ReportTypeExternalRace) { - return GetReportHeaderFromTag(tag) ?: "race on external object"; + const char *str = GetReportHeaderFromTag(tag); + return str ? str : "race on external object"; } if (typ == ReportTypeThreadLeak) return "thread leak"; @@ -170,8 +171,9 @@ static void PrintMop(const ReportMop *mop, bool first) { MopDesc(first, mop->write, mop->atomic), mop->size, (void *)mop->addr, thread_name(thrbuf, mop->tid)); } else { - const char *object_type = - GetObjectTypeFromTag(mop->external_tag) ?: "external object"; + const char *object_type = GetObjectTypeFromTag(mop->external_tag); + if (object_type == nullptr) + object_type = "external object"; Printf(" %s access of %s at %p by %s", ExternalMopDesc(first, mop->write), object_type, (void *)mop->addr, thread_name(thrbuf, mop->tid)); diff --git a/lib/tsan/rtl/tsan_sync.h b/lib/tsan/rtl/tsan_sync.h index d24d697621712..b83c09ff784e1 100644 --- a/lib/tsan/rtl/tsan_sync.h +++ b/lib/tsan/rtl/tsan_sync.h @@ -83,7 +83,7 @@ struct SyncVar { } bool IsFlagSet(u32 f) const { - return atomic_load_relaxed(&flags); + return atomic_load_relaxed(&flags) & f; } void SetFlags(u32 f) { diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 80cc8ad257907..5dabbd8e08cce 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -566,8 +566,14 @@ static void handlePointerOverflowImpl(PointerOverflowData *Data, ScopedReport R(Opts, Loc, ET); - Diag(Loc, DL_Error, "pointer index expression with base %0 overflowed to %1") - << (void *)Base << (void*)Result; + if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) + Diag(Loc, DL_Error, "unsigned pointer index expression result is %0, " + "preceding its base %1") + << (void *)Result << (void *)Base; + else + Diag(Loc, DL_Error, + "pointer index expression with base %0 overflowed to %1") + << (void *)Base << (void *)Result; } void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data, diff --git a/lib/ubsan/ubsan_type_hash_itanium.cc b/lib/ubsan/ubsan_type_hash_itanium.cc index 729c4a0f3739b..dcce0dd85c261 100644 --- a/lib/ubsan/ubsan_type_hash_itanium.cc +++ b/lib/ubsan/ubsan_type_hash_itanium.cc @@ -197,9 +197,9 @@ struct VtablePrefix { }; VtablePrefix *getVtablePrefix(void *Vtable) { VtablePrefix *Vptr = reinterpret_cast<VtablePrefix*>(Vtable); - if (!IsAccessibleMemoryRange((uptr)Vptr, sizeof(VtablePrefix))) - return nullptr; VtablePrefix *Prefix = Vptr - 1; + if (!IsAccessibleMemoryRange((uptr)Prefix, sizeof(VtablePrefix))) + return nullptr; if (!Prefix->TypeInfo) // This can't possibly be a valid vtable. return nullptr; |