Home | History | Annotate | Line # | Download | only in hwasan
hwasan_fuchsia.cpp revision 1.1.1.2
      1      1.1  mrg //===-- hwasan_fuchsia.cpp --------------------------------------*- C++ -*-===//
      2      1.1  mrg //
      3      1.1  mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4      1.1  mrg // See https://llvm.org/LICENSE.txt for license information.
      5      1.1  mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6      1.1  mrg //
      7      1.1  mrg //===----------------------------------------------------------------------===//
      8      1.1  mrg ///
      9      1.1  mrg /// \file
     10      1.1  mrg /// This file is a part of HWAddressSanitizer and contains Fuchsia-specific
     11      1.1  mrg /// code.
     12      1.1  mrg ///
     13      1.1  mrg //===----------------------------------------------------------------------===//
     14      1.1  mrg 
     15      1.1  mrg #include "sanitizer_common/sanitizer_fuchsia.h"
     16      1.1  mrg #if SANITIZER_FUCHSIA
     17      1.1  mrg 
     18  1.1.1.2  mrg #include <zircon/features.h>
     19  1.1.1.2  mrg #include <zircon/syscalls.h>
     20  1.1.1.2  mrg 
     21      1.1  mrg #include "hwasan.h"
     22      1.1  mrg #include "hwasan_interface_internal.h"
     23      1.1  mrg #include "hwasan_report.h"
     24      1.1  mrg #include "hwasan_thread.h"
     25      1.1  mrg #include "hwasan_thread_list.h"
     26      1.1  mrg 
     27      1.1  mrg // This TLS variable contains the location of the stack ring buffer and can be
     28      1.1  mrg // used to always find the hwasan thread object associated with the current
     29      1.1  mrg // running thread.
     30      1.1  mrg [[gnu::tls_model("initial-exec")]]
     31      1.1  mrg SANITIZER_INTERFACE_ATTRIBUTE
     32      1.1  mrg THREADLOCAL uptr __hwasan_tls;
     33      1.1  mrg 
     34      1.1  mrg namespace __hwasan {
     35      1.1  mrg 
     36      1.1  mrg bool InitShadow() {
     37      1.1  mrg   __sanitizer::InitShadowBounds();
     38      1.1  mrg   CHECK_NE(__sanitizer::ShadowBounds.shadow_limit, 0);
     39      1.1  mrg 
     40      1.1  mrg   // These variables are used by MemIsShadow for asserting we have a correct
     41      1.1  mrg   // shadow address. On Fuchsia, we only have one region of shadow, so the
     42      1.1  mrg   // bounds of Low shadow can be zero while High shadow represents the true
     43      1.1  mrg   // bounds. Note that these are inclusive ranges.
     44      1.1  mrg   kLowShadowStart = 0;
     45      1.1  mrg   kLowShadowEnd = 0;
     46      1.1  mrg   kHighShadowStart = __sanitizer::ShadowBounds.shadow_base;
     47      1.1  mrg   kHighShadowEnd = __sanitizer::ShadowBounds.shadow_limit - 1;
     48      1.1  mrg 
     49      1.1  mrg   return true;
     50      1.1  mrg }
     51      1.1  mrg 
     52      1.1  mrg bool MemIsApp(uptr p) {
     53      1.1  mrg   CHECK(GetTagFromPointer(p) == 0);
     54      1.1  mrg   return __sanitizer::ShadowBounds.shadow_limit <= p &&
     55      1.1  mrg          p <= (__sanitizer::ShadowBounds.memory_limit - 1);
     56      1.1  mrg }
     57      1.1  mrg 
     58      1.1  mrg // These are known parameters passed to the hwasan runtime on thread creation.
     59      1.1  mrg struct Thread::InitState {
     60      1.1  mrg   uptr stack_bottom, stack_top;
     61      1.1  mrg };
     62      1.1  mrg 
     63      1.1  mrg static void FinishThreadInitialization(Thread *thread);
     64      1.1  mrg 
     65      1.1  mrg void InitThreads() {
     66      1.1  mrg   // This is the minimal alignment needed for the storage where hwasan threads
     67      1.1  mrg   // and their stack ring buffers are placed. This alignment is necessary so the
     68      1.1  mrg   // stack ring buffer can perform a simple calculation to get the next element
     69      1.1  mrg   // in the RB. The instructions for this calculation are emitted by the
     70      1.1  mrg   // compiler. (Full explanation in hwasan_thread_list.h.)
     71      1.1  mrg   uptr alloc_size = UINT64_C(1) << kShadowBaseAlignment;
     72      1.1  mrg   uptr thread_start = reinterpret_cast<uptr>(
     73      1.1  mrg       MmapAlignedOrDieOnFatalError(alloc_size, alloc_size, __func__));
     74      1.1  mrg 
     75      1.1  mrg   InitThreadList(thread_start, alloc_size);
     76      1.1  mrg 
     77      1.1  mrg   // Create the hwasan thread object for the current (main) thread. Stack info
     78      1.1  mrg   // for this thread is known from information passed via
     79      1.1  mrg   // __sanitizer_startup_hook.
     80      1.1  mrg   const Thread::InitState state = {
     81      1.1  mrg       .stack_bottom = __sanitizer::MainThreadStackBase,
     82      1.1  mrg       .stack_top =
     83      1.1  mrg           __sanitizer::MainThreadStackBase + __sanitizer::MainThreadStackSize,
     84      1.1  mrg   };
     85      1.1  mrg   FinishThreadInitialization(hwasanThreadList().CreateCurrentThread(&state));
     86      1.1  mrg }
     87      1.1  mrg 
     88      1.1  mrg uptr *GetCurrentThreadLongPtr() { return &__hwasan_tls; }
     89      1.1  mrg 
     90      1.1  mrg // This is called from the parent thread before the new thread is created. Here
     91      1.1  mrg // we can propagate known info like the stack bounds to Thread::Init before
     92      1.1  mrg // jumping into the thread. We cannot initialize the stack ring buffer yet since
     93      1.1  mrg // we have not entered the new thread.
     94      1.1  mrg static void *BeforeThreadCreateHook(uptr user_id, bool detached,
     95      1.1  mrg                                     const char *name, uptr stack_bottom,
     96      1.1  mrg                                     uptr stack_size) {
     97      1.1  mrg   const Thread::InitState state = {
     98      1.1  mrg       .stack_bottom = stack_bottom,
     99      1.1  mrg       .stack_top = stack_bottom + stack_size,
    100      1.1  mrg   };
    101      1.1  mrg   return hwasanThreadList().CreateCurrentThread(&state);
    102      1.1  mrg }
    103      1.1  mrg 
    104      1.1  mrg // This sets the stack top and bottom according to the InitState passed to
    105      1.1  mrg // CreateCurrentThread above.
    106      1.1  mrg void Thread::InitStackAndTls(const InitState *state) {
    107      1.1  mrg   CHECK_NE(state->stack_bottom, 0);
    108      1.1  mrg   CHECK_NE(state->stack_top, 0);
    109      1.1  mrg   stack_bottom_ = state->stack_bottom;
    110      1.1  mrg   stack_top_ = state->stack_top;
    111      1.1  mrg   tls_end_ = tls_begin_ = 0;
    112      1.1  mrg }
    113      1.1  mrg 
    114      1.1  mrg // This is called after creating a new thread with the pointer returned by
    115      1.1  mrg // BeforeThreadCreateHook. We are still in the creating thread and should check
    116      1.1  mrg // if it was actually created correctly.
    117      1.1  mrg static void ThreadCreateHook(void *hook, bool aborted) {
    118      1.1  mrg   Thread *thread = static_cast<Thread *>(hook);
    119      1.1  mrg   if (!aborted) {
    120      1.1  mrg     // The thread was created successfully.
    121      1.1  mrg     // ThreadStartHook can already be running in the new thread.
    122      1.1  mrg   } else {
    123      1.1  mrg     // The thread wasn't created after all.
    124      1.1  mrg     // Clean up everything we set up in BeforeThreadCreateHook.
    125      1.1  mrg     atomic_signal_fence(memory_order_seq_cst);
    126      1.1  mrg     hwasanThreadList().ReleaseThread(thread);
    127      1.1  mrg   }
    128      1.1  mrg }
    129      1.1  mrg 
    130      1.1  mrg // This is called in the newly-created thread before it runs anything else,
    131      1.1  mrg // with the pointer returned by BeforeThreadCreateHook (above). Here we can
    132      1.1  mrg // setup the stack ring buffer.
    133      1.1  mrg static void ThreadStartHook(void *hook, thrd_t self) {
    134      1.1  mrg   Thread *thread = static_cast<Thread *>(hook);
    135      1.1  mrg   FinishThreadInitialization(thread);
    136      1.1  mrg   thread->EnsureRandomStateInited();
    137      1.1  mrg }
    138      1.1  mrg 
    139      1.1  mrg // This is the function that sets up the stack ring buffer and enables us to use
    140      1.1  mrg // GetCurrentThread. This function should only be called while IN the thread
    141      1.1  mrg // that we want to create the hwasan thread object for so __hwasan_tls can be
    142      1.1  mrg // properly referenced.
    143      1.1  mrg static void FinishThreadInitialization(Thread *thread) {
    144      1.1  mrg   CHECK_NE(thread, nullptr);
    145      1.1  mrg 
    146      1.1  mrg   // The ring buffer is located immediately before the thread object.
    147      1.1  mrg   uptr stack_buffer_size = hwasanThreadList().GetRingBufferSize();
    148      1.1  mrg   uptr stack_buffer_start = reinterpret_cast<uptr>(thread) - stack_buffer_size;
    149      1.1  mrg   thread->InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
    150      1.1  mrg }
    151      1.1  mrg 
    152      1.1  mrg static void ThreadExitHook(void *hook, thrd_t self) {
    153      1.1  mrg   Thread *thread = static_cast<Thread *>(hook);
    154      1.1  mrg   atomic_signal_fence(memory_order_seq_cst);
    155      1.1  mrg   hwasanThreadList().ReleaseThread(thread);
    156      1.1  mrg }
    157      1.1  mrg 
    158      1.1  mrg uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
    159      1.1  mrg   CHECK(IsAligned(p, kShadowAlignment));
    160      1.1  mrg   CHECK(IsAligned(size, kShadowAlignment));
    161      1.1  mrg   __sanitizer_fill_shadow(p, size, tag,
    162      1.1  mrg                           common_flags()->clear_shadow_mmap_threshold);
    163      1.1  mrg   return AddTagToPointer(p, tag);
    164      1.1  mrg }
    165      1.1  mrg 
    166      1.1  mrg // Not implemented because Fuchsia does not use signal handlers.
    167      1.1  mrg void HwasanOnDeadlySignal(int signo, void *info, void *context) {}
    168      1.1  mrg 
    169      1.1  mrg // Not implemented because Fuchsia does not use interceptors.
    170      1.1  mrg void InitializeInterceptors() {}
    171      1.1  mrg 
    172      1.1  mrg // Not implemented because this is only relevant for Android.
    173      1.1  mrg void AndroidTestTlsSlot() {}
    174      1.1  mrg 
    175      1.1  mrg // TSD was normally used on linux as a means of calling the hwasan thread exit
    176      1.1  mrg // handler passed to pthread_key_create. This is not needed on Fuchsia because
    177      1.1  mrg // we will be using __sanitizer_thread_exit_hook.
    178      1.1  mrg void HwasanTSDInit() {}
    179      1.1  mrg void HwasanTSDThreadInit() {}
    180      1.1  mrg 
    181      1.1  mrg // On linux, this just would call `atexit(HwasanAtExit)`. The functions in
    182      1.1  mrg // HwasanAtExit are unimplemented for Fuchsia and effectively no-ops, so this
    183      1.1  mrg // function is unneeded.
    184      1.1  mrg void InstallAtExitHandler() {}
    185      1.1  mrg 
    186      1.1  mrg void HwasanInstallAtForkHandler() {}
    187      1.1  mrg 
    188  1.1.1.2  mrg void InstallAtExitCheckLeaks() {}
    189  1.1.1.2  mrg 
    190  1.1.1.2  mrg void InitializeOsSupport() {
    191  1.1.1.2  mrg #ifdef __aarch64__
    192  1.1.1.2  mrg   uint32_t features = 0;
    193  1.1.1.2  mrg   CHECK_EQ(zx_system_get_features(ZX_FEATURE_KIND_ADDRESS_TAGGING, &features),
    194  1.1.1.2  mrg            ZX_OK);
    195  1.1.1.2  mrg   if (!(features & ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI) &&
    196  1.1.1.2  mrg       flags()->fail_without_syscall_abi) {
    197  1.1.1.2  mrg     Printf(
    198  1.1.1.2  mrg         "FATAL: HWAddressSanitizer requires "
    199  1.1.1.2  mrg         "ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI.\n");
    200  1.1.1.2  mrg     Die();
    201  1.1.1.2  mrg   }
    202  1.1.1.2  mrg #endif
    203  1.1.1.2  mrg }
    204      1.1  mrg 
    205      1.1  mrg }  // namespace __hwasan
    206      1.1  mrg 
    207  1.1.1.2  mrg namespace __lsan {
    208  1.1.1.2  mrg 
    209  1.1.1.2  mrg bool UseExitcodeOnLeak() { return __hwasan::flags()->halt_on_error; }
    210  1.1.1.2  mrg 
    211  1.1.1.2  mrg }  // namespace __lsan
    212  1.1.1.2  mrg 
    213      1.1  mrg extern "C" {
    214      1.1  mrg 
    215      1.1  mrg void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
    216      1.1  mrg                                             const char *name, void *stack_base,
    217      1.1  mrg                                             size_t stack_size) {
    218      1.1  mrg   return __hwasan::BeforeThreadCreateHook(
    219      1.1  mrg       reinterpret_cast<uptr>(thread), detached, name,
    220      1.1  mrg       reinterpret_cast<uptr>(stack_base), stack_size);
    221      1.1  mrg }
    222      1.1  mrg 
    223      1.1  mrg void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
    224      1.1  mrg   __hwasan::ThreadCreateHook(hook, error != thrd_success);
    225      1.1  mrg }
    226      1.1  mrg 
    227      1.1  mrg void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
    228      1.1  mrg   __hwasan::ThreadStartHook(hook, reinterpret_cast<uptr>(self));
    229      1.1  mrg }
    230      1.1  mrg 
    231      1.1  mrg void __sanitizer_thread_exit_hook(void *hook, thrd_t self) {
    232      1.1  mrg   __hwasan::ThreadExitHook(hook, self);
    233      1.1  mrg }
    234      1.1  mrg 
    235  1.1.1.2  mrg void __sanitizer_module_loaded(const struct dl_phdr_info *info, size_t) {
    236  1.1.1.2  mrg   __hwasan_library_loaded(info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum);
    237  1.1.1.2  mrg }
    238  1.1.1.2  mrg 
    239      1.1  mrg }  // extern "C"
    240      1.1  mrg 
    241      1.1  mrg #endif  // SANITIZER_FUCHSIA
    242