libsanitizer: merge from upstream (87e6e490e79384a5)

This commit is contained in:
Martin Liska 2023-04-30 09:38:14 +02:00
parent d5e2694e82
commit d96e14ceb9
26 changed files with 202 additions and 212 deletions

View File

@ -1,4 +1,4 @@
3185e47b5a8444e9fd70b746a7ad679dd131ffe4
87e6e490e79384a523bc7f0216c3db60227d6d58
The first line of this file holds the git revision number of the
last merge done from the master library sources.

View File

@ -158,6 +158,23 @@ static void CheckODRViolationViaIndicator(const Global *g) {
}
}
// Check ODR violation for given global G by checking if it's already poisoned.
// We use this method in case compiler doesn't use private aliases for global
// variables.
static void CheckODRViolationViaPoisoning(const Global *g) {
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
// This check may not be enough: if the first global is much larger
// the entire redzone of the second global may be within the first global.
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
if (g->beg == l->g->beg &&
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
!IsODRViolationSuppressed(g->name))
ReportODRViolation(g, FindRegistrationSite(g),
l->g, FindRegistrationSite(l->g));
}
}
}
// Clang provides two different ways for global variables protection:
// it can poison the global itself or its private alias. In former
// case we may poison same symbol multiple times, that can help us to
@ -203,6 +220,8 @@ static void RegisterGlobal(const Global *g) {
// where two globals with the same name are defined in different modules.
if (UseODRIndicator(g))
CheckODRViolationViaIndicator(g);
else
CheckODRViolationViaPoisoning(g);
}
if (CanPoisonMemory())
PoisonRedZones(*g);

View File

@ -81,12 +81,7 @@ void InitializePlatformInterceptors();
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
!SANITIZER_NETBSD
# define ASAN_INTERCEPT___CXA_THROW 1
# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \
|| ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# else
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# endif
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
# else

View File

@ -190,7 +190,7 @@
# elif defined(__aarch64__)
# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
# elif defined(__powerpc64__)
# define ASAN_SHADOW_OFFSET_CONST 0x0000020000000000
# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
# elif defined(__s390x__)
# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
# elif SANITIZER_FREEBSD

View File

@ -445,16 +445,32 @@ void __hwasan_print_shadow(const void *p, uptr sz) {
sptr __hwasan_test_shadow(const void *p, uptr sz) {
if (sz == 0)
return -1;
tag_t ptr_tag = GetTagFromPointer((uptr)p);
uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
uptr ptr = reinterpret_cast<uptr>(p);
tag_t ptr_tag = GetTagFromPointer(ptr);
uptr ptr_raw = UntagAddr(ptr);
uptr shadow_first = MemToShadow(ptr_raw);
uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
for (uptr s = shadow_first; s <= shadow_last; ++s)
if (*(tag_t *)s != ptr_tag) {
sptr offset = ShadowToMem(s) - ptr_raw;
uptr shadow_last = MemToShadow(ptr_raw + sz);
for (uptr s = shadow_first; s < shadow_last; ++s) {
if (UNLIKELY(*(tag_t *)s != ptr_tag)) {
uptr short_size =
ShortTagSize(*(tag_t *)s, AddTagToPointer(ShadowToMem(s), ptr_tag));
sptr offset = ShadowToMem(s) - ptr_raw + short_size;
return offset < 0 ? 0 : offset;
}
return -1;
}
uptr end = ptr + sz;
uptr tail_sz = end & (kShadowAlignment - 1);
if (!tail_sz)
return -1;
uptr short_size =
ShortTagSize(*(tag_t *)shadow_last, end & ~(kShadowAlignment - 1));
if (LIKELY(tail_sz <= short_size))
return -1;
sptr offset = sz - tail_sz + short_size;
return offset < 0 ? 0 : offset;
}
u16 __sanitizer_unaligned_load16(const uu16 *p) {

View File

@ -16,6 +16,7 @@
#include "hwasan_flags.h"
#include "hwasan_interface_internal.h"
#include "hwasan_mapping.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
@ -78,12 +79,23 @@ const unsigned kRecordFPShift = 48;
const unsigned kRecordFPLShift = 4;
const unsigned kRecordFPModulus = 1 << (64 - kRecordFPShift + kRecordFPLShift);
static inline bool InTaggableRegion(uptr addr) {
#if defined(HWASAN_ALIASING_MODE)
// Aliases are mapped next to shadow so that the upper bits match the shadow
// base.
return (addr >> kTaggableRegionCheckShift) ==
(__hwasan::GetShadowOffset() >> kTaggableRegionCheckShift);
#endif
return true;
}
static inline tag_t GetTagFromPointer(uptr p) {
return (p >> kAddressTagShift) & kTagMask;
return InTaggableRegion(p) ? ((p >> kAddressTagShift) & kTagMask) : 0;
}
static inline uptr UntagAddr(uptr tagged_addr) {
return tagged_addr & ~kAddressTagMask;
return InTaggableRegion(tagged_addr) ? (tagged_addr & ~kAddressTagMask)
: tagged_addr;
}
static inline void *UntagPtr(const void *tagged_ptr) {
@ -92,7 +104,9 @@ static inline void *UntagPtr(const void *tagged_ptr) {
}
static inline uptr AddTagToPointer(uptr p, tag_t tag) {
return (p & ~kAddressTagMask) | ((uptr)tag << kAddressTagShift);
return InTaggableRegion(p)
? ((p & ~kAddressTagMask) | ((uptr)tag << kAddressTagShift))
: p;
}
namespace __hwasan {

View File

@ -213,7 +213,10 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment,
ReportOutOfMemory(size, stack);
}
if (zeroise) {
internal_memset(allocated, 0, size);
// The secondary allocator mmaps memory, which should be zero-inited so we
// don't need to explicitly clear it.
if (allocator.FromPrimary(allocated))
internal_memset(allocated, 0, size);
} else if (flags()->max_malloc_fill_size > 0) {
uptr fill_size = Min(size, (uptr)flags()->max_malloc_fill_size);
internal_memset(allocated, flags()->malloc_fill_byte, fill_size);
@ -287,9 +290,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
CHECK(tagged_ptr);
RunFreeHooks(tagged_ptr);
bool in_taggable_region =
InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr));
void *untagged_ptr = in_taggable_region ? UntagPtr(tagged_ptr) : tagged_ptr;
void *untagged_ptr = UntagPtr(tagged_ptr);
if (CheckInvalidFree(stack, untagged_ptr, tagged_ptr))
return;
@ -308,6 +309,9 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
u32 alloc_context_id = meta->GetAllocStackId();
u32 alloc_thread_id = meta->GetAllocThreadId();
bool in_taggable_region =
InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr));
// Check tail magic.
uptr tagged_size = TaggedSize(orig_size);
if (flags()->free_checks_tail_magic && orig_size &&
@ -370,10 +374,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old,
uptr new_size, uptr alignment) {
void *untagged_ptr_old =
InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr_old))
? UntagPtr(tagged_ptr_old)
: tagged_ptr_old;
void *untagged_ptr_old = UntagPtr(tagged_ptr_old);
if (CheckInvalidFree(stack, untagged_ptr_old, tagged_ptr_old))
return nullptr;
void *tagged_ptr_new =
@ -381,9 +382,9 @@ static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old,
if (tagged_ptr_old && tagged_ptr_new) {
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(untagged_ptr_old));
internal_memcpy(
UntagPtr(tagged_ptr_new), untagged_ptr_old,
Min(new_size, static_cast<uptr>(meta->GetRequestedSize())));
void *untagged_ptr_new = UntagPtr(tagged_ptr_new);
internal_memcpy(untagged_ptr_new, untagged_ptr_old,
Min(new_size, static_cast<uptr>(meta->GetRequestedSize())));
HwasanDeallocate(stack, tagged_ptr_old);
}
return tagged_ptr_new;
@ -426,12 +427,13 @@ static const void *AllocationBegin(const void *p) {
return (const void *)AddTagToPointer((uptr)beg, tag);
}
static uptr AllocationSize(const void *tagged_ptr) {
const void *untagged_ptr = UntagPtr(tagged_ptr);
static uptr AllocationSize(const void *p) {
const void *untagged_ptr = UntagPtr(p);
if (!untagged_ptr) return 0;
const void *beg = allocator.GetBlockBegin(untagged_ptr);
Metadata *b = (Metadata *)allocator.GetMetaData(untagged_ptr);
if (beg != untagged_ptr) return 0;
if (!beg)
return 0;
Metadata *b = (Metadata *)allocator.GetMetaData(beg);
return b->GetRequestedSize();
}
@ -540,7 +542,7 @@ void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
}
uptr PointsIntoChunk(void *p) {
p = __hwasan::InTaggableRegion(reinterpret_cast<uptr>(p)) ? UntagPtr(p) : p;
p = UntagPtr(p);
uptr addr = reinterpret_cast<uptr>(p);
uptr chunk =
reinterpret_cast<uptr>(__hwasan::allocator.GetBlockBeginFastLocked(p));
@ -558,8 +560,7 @@ uptr PointsIntoChunk(void *p) {
}
uptr GetUserBegin(uptr chunk) {
if (__hwasan::InTaggableRegion(chunk))
CHECK_EQ(UntagAddr(chunk), chunk);
CHECK_EQ(UntagAddr(chunk), chunk);
void *block = __hwasan::allocator.GetBlockBeginFastLocked(
reinterpret_cast<void *>(chunk));
if (!block)
@ -573,15 +574,14 @@ uptr GetUserBegin(uptr chunk) {
}
uptr GetUserAddr(uptr chunk) {
tag_t mem_tag = *(tag_t *)__hwasan::MemToShadow(chunk);
if (!__hwasan::InTaggableRegion(chunk))
if (!InTaggableRegion(chunk))
return chunk;
tag_t mem_tag = *(tag_t *)__hwasan::MemToShadow(chunk);
return AddTagToPointer(chunk, mem_tag);
}
LsanMetadata::LsanMetadata(uptr chunk) {
if (__hwasan::InTaggableRegion(chunk))
CHECK_EQ(UntagAddr(chunk), chunk);
CHECK_EQ(UntagAddr(chunk), chunk);
metadata_ =
chunk ? __hwasan::allocator.GetMetaData(reinterpret_cast<void *>(chunk))
: nullptr;
@ -619,7 +619,7 @@ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
}
IgnoreObjectResult IgnoreObject(const void *p) {
p = __hwasan::InTaggableRegion(reinterpret_cast<uptr>(p)) ? UntagPtr(p) : p;
p = UntagPtr(p);
uptr addr = reinterpret_cast<uptr>(p);
uptr chunk = reinterpret_cast<uptr>(__hwasan::allocator.GetBlockBegin(p));
if (!chunk)
@ -674,3 +674,5 @@ const void *__sanitizer_get_allocated_begin(const void *p) {
}
uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); }

View File

@ -127,16 +127,6 @@ typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;
void GetAllocatorStats(AllocatorStatCounters s);
inline bool InTaggableRegion(uptr addr) {
#if defined(HWASAN_ALIASING_MODE)
// Aliases are mapped next to shadow so that the upper bits match the shadow
// base.
return (addr >> kTaggableRegionCheckShift) ==
(GetShadowOffset() >> kTaggableRegionCheckShift);
#endif
return true;
}
} // namespace __hwasan
#endif // HWASAN_ALLOCATOR_H

View File

@ -125,8 +125,22 @@ __attribute__((always_inline)) static void SigTrap(uptr p, uptr size) {
// __builtin_unreachable();
}
__attribute__((always_inline, nodebug)) static bool PossiblyShortTagMatches(
tag_t mem_tag, uptr ptr, uptr sz) {
__attribute__((always_inline, nodebug)) static inline uptr ShortTagSize(
tag_t mem_tag, uptr ptr) {
DCHECK(IsAligned(ptr, kShadowAlignment));
tag_t ptr_tag = GetTagFromPointer(ptr);
if (ptr_tag == mem_tag)
return kShadowAlignment;
if (!mem_tag || mem_tag >= kShadowAlignment)
return 0;
if (*(u8 *)(ptr | (kShadowAlignment - 1)) != ptr_tag)
return 0;
return mem_tag;
}
__attribute__((always_inline, nodebug)) static inline bool
PossiblyShortTagMatches(tag_t mem_tag, uptr ptr, uptr sz) {
DCHECK(IsAligned(ptr, kShadowAlignment));
tag_t ptr_tag = GetTagFromPointer(ptr);
if (ptr_tag == mem_tag)
return true;
@ -134,9 +148,6 @@ __attribute__((always_inline, nodebug)) static bool PossiblyShortTagMatches(
return false;
if ((ptr & (kShadowAlignment - 1)) + sz > mem_tag)
return false;
#if !defined(__aarch64__) && !(SANITIZER_RISCV64)
ptr = UntagAddr(ptr);
#endif
return *(u8 *)(ptr | (kShadowAlignment - 1)) == ptr_tag;
}
@ -169,7 +180,7 @@ __attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
__builtin_unreachable();
}
uptr end = p + sz;
uptr tail_sz = end & 0xf;
uptr tail_sz = end & (kShadowAlignment - 1);
if (UNLIKELY(tail_sz != 0 &&
!PossiblyShortTagMatches(
*shadow_last, end & ~(kShadowAlignment - 1), tail_sz))) {

View File

@ -14,9 +14,11 @@
// sanitizer_common/sanitizer_common_interceptors.h
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
#include "hwasan.h"
#include "hwasan_checks.h"
#include "hwasan_thread.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#if !SANITIZER_FUCHSIA
@ -28,31 +30,47 @@ using namespace __hwasan;
struct ThreadStartArg {
thread_callback_t callback;
void *param;
__sanitizer_sigset_t starting_sigset_;
};
static void *HwasanThreadStartFunc(void *arg) {
__hwasan_thread_enter();
ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg);
SetSigProcMask(&A.starting_sigset_, nullptr);
UnmapOrDie(arg, GetPageSizeCached());
return A.callback(A.param);
}
# define COMMON_SYSCALL_PRE_READ_RANGE(p, s) __hwasan_loadN((uptr)p, (uptr)s)
# define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
__hwasan_storeN((uptr)p, (uptr)s)
# define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
do { \
(void)(p); \
(void)(s); \
} while (false)
# define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
do { \
(void)(p); \
(void)(s); \
} while (false)
# include "sanitizer_common/sanitizer_common_syscalls.inc"
# include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
void * param) {
EnsureMainThreadIDIsCorrect();
ScopedTaggingDisabler tagging_disabler;
ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie(
GetPageSizeCached(), "pthread_create"));
*A = {callback, param};
int res;
{
// ASAN uses the same approach to disable leaks from pthread_create.
A->callback = callback;
A->param = param;
ScopedBlockSignals block(&A->starting_sigset_);
// ASAN uses the same approach to disable leaks from pthread_create.
# if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler lsan_disabler;
__lsan::ScopedInterceptorDisabler lsan_disabler;
# endif
res = REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A);
}
return res;
return REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A);
}
INTERCEPTOR(int, pthread_join, void *t, void **arg) {

View File

@ -7748,8 +7748,7 @@ static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
pp_size * sizeof(char **));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *));
}
INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
@ -7855,8 +7854,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
}
return n;
}
@ -7877,8 +7875,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
}
return n;
}
@ -7897,8 +7894,7 @@ INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
nn_size * sizeof(char **));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
}
return n;
}
@ -10090,41 +10086,6 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
#define INIT_GETRANDOM
#endif
#if SANITIZER_INTERCEPT_CRYPT
INTERCEPTOR(char *, crypt, char *key, char *salt) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
char *res = REAL(crypt)(key, salt);
if (res != nullptr)
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
#else
#define INIT_CRYPT
#endif
#if SANITIZER_INTERCEPT_CRYPT_R
INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
char *res = REAL(crypt_r)(key, salt, data);
if (res != nullptr) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
__sanitizer::struct_crypt_data_sz);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
}
return res;
}
#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
#else
#define INIT_CRYPT_R
#endif
#if SANITIZER_INTERCEPT_GETENTROPY
INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
void *ctx;
@ -10702,8 +10663,6 @@ static void InitializeCommonInterceptors() {
INIT_GETUSERSHELL;
INIT_SL_INIT;
INIT_GETRANDOM;
INIT_CRYPT;
INIT_CRYPT_R;
INIT_GETENTROPY;
INIT_QSORT;
INIT_QSORT_R;

View File

@ -1374,9 +1374,8 @@ PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) {
}
POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) {
if (res >= 0) {
if (ctx)
POST_WRITE(ctx, sizeof(*ctx));
if (res >= 0 && ctx) {
POST_WRITE(ctx, sizeof(*ctx));
// (*ctx) is actually a pointer to a kernel mapped page, and there are
// people out there who are crazy enough to peek into that page's 32-byte
// header.

View File

@ -838,13 +838,9 @@ u32 GetNumberOfCPUs() {
#elif SANITIZER_SOLARIS
return sysconf(_SC_NPROCESSORS_ONLN);
#else
#if defined(CPU_COUNT)
cpu_set_t CPUs;
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
return CPU_COUNT(&CPUs);
#else
return 1;
#endif
#endif
}

View File

@ -38,7 +38,7 @@
extern char **environ;
# endif
# if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
# if defined(__has_include) && __has_include(<os/trace.h>)
# define SANITIZER_OS_TRACE 1
# include <os/trace.h>
# else
@ -71,15 +71,7 @@ extern char ***_NSGetArgv(void);
# include <mach/mach_time.h>
# include <mach/vm_statistics.h>
# include <malloc/malloc.h>
# if defined(__has_builtin) && __has_builtin(__builtin_os_log_format)
# include <os/log.h>
# else
/* Without support for __builtin_os_log_format, fall back to the older
method. */
# define OS_LOG_DEFAULT 0
# define os_log_error(A,B,C) \
asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", (C));
# endif
# include <os/log.h>
# include <pthread.h>
# include <pthread/introspection.h>
# include <sched.h>

View File

@ -14,26 +14,6 @@
#include "sanitizer_common.h"
#include "sanitizer_platform.h"
/* TARGET_OS_OSX is not present in SDKs before Darwin16 (macOS 10.12) use
TARGET_OS_MAC (we have no support for iOS in any form for these versions,
so there's no ambiguity). */
#if !defined(TARGET_OS_OSX) && TARGET_OS_MAC
# define TARGET_OS_OSX 1
#endif
/* Other TARGET_OS_xxx are not present on earlier versions, define them to
0 (we have no support for them; they are not valid targets anyway). */
#ifndef TARGET_OS_IOS
#define TARGET_OS_IOS 0
#endif
#ifndef TARGET_OS_TV
#define TARGET_OS_TV 0
#endif
#ifndef TARGET_OS_WATCH
#define TARGET_OS_WATCH 0
#endif
#if SANITIZER_APPLE
#include "sanitizer_posix.h"

View File

@ -569,8 +569,6 @@
#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_GETRANDOM \
((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)

View File

@ -26,10 +26,7 @@
// With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
// are not defined anywhere in userspace headers. Fake them. This seems to work
// fine with newer headers, too. Beware that with <sys/stat.h>, struct stat
// takes the form of struct stat64 on 32-bit platforms if _FILE_OFFSET_BITS=64.
// Also, for some platforms (e.g. mips) there are additional members in the
// <sys/stat.h> struct stat:s.
// fine with newer headers, too.
#include <linux/posix_types.h>
# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
# include <sys/stat.h>

View File

@ -177,10 +177,6 @@ typedef struct user_fpregs elf_fpregset_t;
# include "sanitizer_platform_interceptors.h"
# include "sanitizer_platform_limits_posix.h"
#if SANITIZER_INTERCEPT_CRYPT_R
#include <crypt.h>
#endif
namespace __sanitizer {
unsigned struct_utsname_sz = sizeof(struct utsname);
unsigned struct_stat_sz = sizeof(struct stat);
@ -300,10 +296,6 @@ namespace __sanitizer {
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
#endif // SANITIZER_GLIBC
#if SANITIZER_INTERCEPT_CRYPT_R
unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
unsigned struct_timex_sz = sizeof(struct timex);
unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);

View File

@ -309,7 +309,6 @@ extern unsigned struct_msqid_ds_sz;
extern unsigned struct_mq_attr_sz;
extern unsigned struct_timex_sz;
extern unsigned struct_statvfs_sz;
extern unsigned struct_crypt_data_sz;
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
struct __sanitizer_iovec {
@ -578,8 +577,13 @@ struct __sanitizer_sigset_t {
#endif
struct __sanitizer_siginfo_pad {
#if SANITIZER_X32
// x32 siginfo_t is aligned to 8 bytes.
u64 pad[128 / sizeof(u64)];
#else
// Require uptr, because siginfo_t is always pointer-size aligned on Linux.
uptr pad[128 / sizeof(uptr)];
#endif
};
#if SANITIZER_LINUX

View File

@ -146,13 +146,8 @@ static bool IsDyldHdr(const mach_header *hdr) {
// until we hit a Mach header matching dyld instead. These recurse
// calls are expensive, but the first memory map generation occurs
// early in the process, when dyld is one of the only images loaded,
// so it will be hit after only a few iterations. These assumptions don't
// hold on macOS 13+ anymore (dyld itself has moved into the shared cache).
// FIXME: Unfortunately, the upstream revised version to deal with macOS 13+
// is incompatible with GCC and also uses APIs not available on earlier
// systems which we support; backed out for now.
// so it will be hit after only a few iterations. These assumptions don't hold
// on macOS 13+ anymore (dyld itself has moved into the shared cache).
static mach_header *GetDyldImageHeaderViaVMRegion() {
vm_address_t address = 0;
@ -176,17 +171,64 @@ static mach_header *GetDyldImageHeaderViaVMRegion() {
}
}
extern "C" {
struct dyld_shared_cache_dylib_text_info {
uint64_t version; // current version 2
// following fields all exist in version 1
uint64_t loadAddressUnslid;
uint64_t textSegmentSize;
uuid_t dylibUuid;
const char *path; // pointer invalid at end of iterations
// following fields all exist in version 2
uint64_t textSegmentOffset; // offset from start of cache
};
typedef struct dyld_shared_cache_dylib_text_info
dyld_shared_cache_dylib_text_info;
extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
extern const void *_dyld_get_shared_cache_range(size_t *length);
extern int dyld_shared_cache_iterate_text(
const uuid_t cacheUuid,
void (^callback)(const dyld_shared_cache_dylib_text_info *info));
} // extern "C"
static mach_header *GetDyldImageHeaderViaSharedCache() {
uuid_t uuid;
bool hasCache = _dyld_get_shared_cache_uuid(uuid);
if (!hasCache)
return nullptr;
size_t cacheLength;
__block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
CHECK(cacheStart && cacheLength);
__block mach_header *dyldHdr = nullptr;
int res = dyld_shared_cache_iterate_text(
uuid, ^(const dyld_shared_cache_dylib_text_info *info) {
CHECK_GE(info->version, 2);
mach_header *hdr =
(mach_header *)(cacheStart + info->textSegmentOffset);
if (IsDyldHdr(hdr))
dyldHdr = hdr;
});
CHECK_EQ(res, 0);
return dyldHdr;
}
const mach_header *get_dyld_hdr() {
if (!dyld_hdr) {
// On macOS 13+, dyld itself has moved into the shared cache. Looking it up
// via vm_region_recurse_64() causes spins/hangs/crashes.
// FIXME: find a way to do this compatible with GCC.
if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) {
dyld_hdr = GetDyldImageHeaderViaSharedCache();
if (!dyld_hdr) {
VReport(1,
"looking up the dyld image header in the shared cache on "
"macOS 13+ is not yet supported. Falling back to "
"Failed to lookup the dyld image header in the shared cache on "
"macOS 13+ (or no shared cache in use). Falling back to "
"lookup via vm_region_recurse_64().\n");
dyld_hdr = GetDyldImageHeaderViaVMRegion();
}
} else {
dyld_hdr = GetDyldImageHeaderViaVMRegion();
}

View File

@ -87,8 +87,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp,
// Nope, this does not look right either. This means the frame after next does
// not have a valid frame pointer, but we can still extract the caller PC.
// Unfortunately, there is no way to decide between GCC and LLVM frame
// layouts. Assume GCC.
return bp_prev - 1;
// layouts. Assume LLVM.
return bp_prev;
#else
return (uhwptr*)bp;
#endif
@ -111,21 +111,14 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
IsAligned((uptr)frame, sizeof(*frame)) &&
size < max_depth) {
#ifdef __powerpc__
// PowerPC ABIs specify that the return address is saved on the
// *caller's* stack frame. Thus we must dereference the back chain
// to find the caller frame before extracting it.
// PowerPC ABIs specify that the return address is saved at offset
// 16 of the *caller's* stack frame. Thus we must dereference the
// back chain to find the caller frame before extracting it.
uhwptr *caller_frame = (uhwptr*)frame[0];
if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
!IsAligned((uptr)caller_frame, sizeof(uhwptr)))
break;
// For most ABIs the offset where the return address is saved is two
// register sizes. The exception is the SVR4 ABI, which uses an
// offset of only one register size.
#ifdef _CALL_SYSV
uhwptr pc1 = caller_frame[1];
#else
uhwptr pc1 = caller_frame[2];
#endif
#elif defined(__s390__)
uhwptr pc1 = frame[14];
#elif defined(__loongarch__) || defined(__riscv)

View File

@ -1,6 +1,5 @@
#include "tsan_ppc_regs.h"
.machine altivec
.section .text
.hidden __tsan_setjmp
.globl _setjmp

View File

@ -50,7 +50,6 @@ void InitializeFlags() {
{
CommonFlags cf;
cf.CopyFrom(*common_flags());
cf.print_summary = false;
cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
OverrideCommonFlags(cf);
}

View File

@ -894,21 +894,6 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
} // namespace __ubsan
void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData,
ValueHandle Function) {
GET_REPORT_OPTIONS(false);
CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
handleCFIBadIcall(&Data, Function, Opts);
}
void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *CallData,
ValueHandle Function) {
GET_REPORT_OPTIONS(true);
CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
handleCFIBadIcall(&Data, Function, Opts);
Die();
}
void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
ValueHandle Value,
uptr ValidVtable) {

View File

@ -215,20 +215,12 @@ enum CFITypeCheckKind : unsigned char {
CFITCK_VMFCall,
};
struct CFIBadIcallData {
SourceLocation Loc;
const TypeDescriptor &Type;
};
struct CFICheckFailData {
CFITypeCheckKind CheckKind;
SourceLocation Loc;
const TypeDescriptor &Type;
};
/// \brief Handle control flow integrity failure for indirect function calls.
RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function)
/// \brief Handle control flow integrity failures.
RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
uptr VtableIsValid)

View File

@ -12,7 +12,6 @@
#ifndef UBSAN_PLATFORM_H
#define UBSAN_PLATFORM_H
#ifndef CAN_SANITIZE_UB
// Other platforms should be easy to add, and probably work as-is.
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
defined(__NetBSD__) || defined(__DragonFly__) || \
@ -22,6 +21,5 @@
#else
# define CAN_SANITIZE_UB 0
#endif
#endif //CAN_SANITIZE_UB
#endif