summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-16 21:03:53 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-16 21:03:53 +0000
commit4658ff5fee0369e08fe69bce90019fad154d9330 (patch)
tree5ac9da286baff9e296c083f060fc58b2e53b63bf /lib
parent7edd24de96f22ad70fd3ca16a3c51723383cd58b (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/asan/asan_allocator.cc21
-rw-r--r--lib/sanitizer_common/sanitizer_allocator_combined.h19
-rw-r--r--lib/sanitizer_common/sanitizer_allocator_secondary.h7
-rw-r--r--lib/sanitizer_common/sanitizer_common.h3
-rw-r--r--lib/sanitizer_common/sanitizer_flags.inc3
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc9
-rw-r--r--lib/sanitizer_common/sanitizer_linux_libcdep.cc1
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc15
-rw-r--r--lib/sanitizer_common/sanitizer_posix.cc16
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc10
-rw-r--r--lib/tsan/rtl/tsan_report.cc8
-rw-r--r--lib/tsan/rtl/tsan_sync.h2
-rw-r--r--lib/ubsan/ubsan_handlers.cc10
-rw-r--r--lib/ubsan/ubsan_type_hash_itanium.cc4
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;