libsanitizer: Apply local patches
authorMartin Liska <mliska@suse.cz>
Thu, 5 May 2022 10:52:44 +0000 (12:52 +0200)
committerMartin Liska <mliska@suse.cz>
Tue, 15 Nov 2022 15:44:59 +0000 (16:44 +0100)
14 files changed:
libsanitizer/asan/asan_globals.cpp
libsanitizer/asan/asan_interceptors.h
libsanitizer/asan/asan_mapping.h
libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_mac.cpp
libsanitizer/sanitizer_common/sanitizer_mac.h
libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp
libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp
libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp
libsanitizer/tsan/tsan_rtl_ppc64.S
libsanitizer/ubsan/ubsan_flags.cpp
libsanitizer/ubsan/ubsan_handlers.cpp
libsanitizer/ubsan/ubsan_handlers.h
libsanitizer/ubsan/ubsan_platform.h

index b780128..8f3491f 100644 (file)
@@ -154,23 +154,6 @@ 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
@@ -216,8 +199,6 @@ 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);
index c4bf087..9a6c22c 100644 (file)
@@ -81,7 +81,12 @@ void InitializePlatformInterceptors();
 #if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
     !SANITIZER_NETBSD
 # define ASAN_INTERCEPT___CXA_THROW 1
-# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 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
 # if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
 #  define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
 # else
index c5f95c0..47ccf84 100644 (file)
 #  elif defined(__aarch64__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
 #  elif defined(__powerpc64__)
-#    define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
+#    define ASAN_SHADOW_OFFSET_CONST 0x0000020000000000
 #  elif defined(__s390x__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
 #  elif SANITIZER_FREEBSD
index d74851c..56d2316 100644 (file)
@@ -822,9 +822,13 @@ 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
 }
 
index 23c4c66..a2591e9 100644 (file)
@@ -38,7 +38,7 @@
 extern char **environ;
 #endif
 
-#if defined(__has_include) && __has_include(<os/trace.h>)
+#if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
 #define SANITIZER_OS_TRACE 1
 #include <os/trace.h>
 #else
@@ -71,7 +71,15 @@ extern "C" {
 #include <mach/mach_time.h>
 #include <mach/vm_statistics.h>
 #include <malloc/malloc.h>
-#include <os/log.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 <pthread.h>
 #include <pthread/introspection.h>
 #include <sched.h>
index f0a97d0..1cf2e29 100644 (file)
 
 #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"
 
index bf0f355..c278c87 100644 (file)
 
 // 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.
+// 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.
 #include <linux/posix_types.h>
 #  if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
 #    include <sys/stat.h>
index 4b0e678..ba4259a 100644 (file)
@@ -146,8 +146,13 @@ 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).
+// 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.
+
 static mach_header *GetDyldImageHeaderViaVMRegion() {
   vm_address_t address = 0;
 
@@ -171,64 +176,17 @@ 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,
-                "Failed to lookup the dyld image header in the shared cache on "
-                "macOS 13+ (or no shared cache in use).  Falling back to "
+                "looking up the dyld image header in the shared cache on "
+                "macOS 13+ is not yet supported.  Falling back to "
                 "lookup via vm_region_recurse_64().\n");
         dyld_hdr = GetDyldImageHeaderViaVMRegion();
-      }
     } else {
       dyld_hdr = GetDyldImageHeaderViaVMRegion();
     }
index d24fae9..661495e 100644 (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 LLVM.
-  return bp_prev;
+  // layouts. Assume GCC.
+  return bp_prev - 1;
 #else
   return (uhwptr*)bp;
 #endif
@@ -111,14 +111,21 @@ 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 at offset
-    // 16 of 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 on 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)
index 8285e21..9e533a7 100644 (file)
@@ -1,5 +1,6 @@
 #include "tsan_ppc_regs.h"
 
+        .machine altivec
         .section .text
         .hidden __tsan_setjmp
         .globl _setjmp
index 25cefd4..9a66bd3 100644 (file)
@@ -50,6 +50,7 @@ void InitializeFlags() {
   {
     CommonFlags cf;
     cf.CopyFrom(*common_flags());
+    cf.print_summary = false;
     cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
     OverrideCommonFlags(cf);
   }
index 410292a..970075e 100644 (file)
@@ -894,6 +894,21 @@ 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) {
index 219fb15..9f41235 100644 (file)
@@ -215,12 +215,20 @@ 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)
index d2cc2e1..ad3e883 100644 (file)
@@ -12,6 +12,7 @@
 #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__) ||                           \
@@ -21,5 +22,6 @@
 #else
 # define CAN_SANITIZE_UB 0
 #endif
+#endif //CAN_SANITIZE_UB
 
 #endif