1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "asan_impl.h" 6#include "zircon_impl.h" 7#include "libc.h" 8 9#include <limits.h> 10#include <zircon/process.h> 11#include <zircon/syscalls.h> 12 13#define ASAN_SHADOW_SHIFT 3 14 15#define SHADOW_VMO_NAME "asan-shadow" 16 17#if __has_feature(address_sanitizer) 18 19static sanitizer_shadow_bounds_t shadow_bounds ATTR_RELRO; 20 21__NO_SAFESTACK NO_ASAN void __asan_early_init(void) { 22 zx_info_vmar_t info; 23 zx_status_t status = _zx_object_get_info(__zircon_vmar_root_self, 24 ZX_INFO_VMAR, &info, sizeof(info), 25 NULL, NULL); 26 if (status != ZX_OK) 27 __builtin_trap(); 28 29 // Find the top of the accessible address space. 30 uintptr_t top = info.base + info.len; 31 32 // Round it up to a power-of-two size. There may be some pages at 33 // the top that can't actually be mapped, but for purposes of the 34 // the shadow, we'll pretend they could be. 35 int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top); 36 if (top != (uintptr_t)1 << bit) 37 top = (uintptr_t)1 << (bit + 1); 38 39 // The shadow is a fraction of the address space at the bottom. 40 size_t shadow_virtual_size = top >> ASAN_SHADOW_SHIFT; 41 42 // The shadow of the shadow is never used, so it'll be left unmapped. 43 size_t shadow_shadow_size = shadow_virtual_size >> ASAN_SHADOW_SHIFT; 44 45 // The VMAR reserved for the shadow covers the region from the 46 // lowest permitted mapping address (info.base) up to the notional 47 // top of the shadow (shadow_virtual_size). 48 zx_handle_t shadow_vmar; 49 uintptr_t shadow_addr; 50 status = _zx_vmar_allocate( 51 __zircon_vmar_root_self, 52 ZX_VM_SPECIFIC | ZX_VM_CAN_MAP_SPECIFIC | 53 ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE, 54 0, shadow_virtual_size - info.base, &shadow_vmar, &shadow_addr); 55 if (status != ZX_OK || shadow_addr != info.base) 56 __builtin_trap(); 57 58 // The actual shadow that needs to be mapped starts at the top of 59 // the shadow of the shadow, and has a page of shadow for each 60 // (1<<ASAN_SHADOW_SHIFT) pages that can actually be mapped. 61 size_t shadow_used_size = 62 ((((info.base + info.len) >> ASAN_SHADOW_SHIFT) + 63 PAGE_SIZE - 1) & -PAGE_SIZE) - 64 shadow_shadow_size; 65 66 // Now we're ready to allocate and map the actual shadow. 67 zx_handle_t vmo; 68 status = _zx_vmo_create(shadow_used_size, 0, &vmo); 69 if (status != ZX_OK) 70 __builtin_trap(); 71 _zx_object_set_property(vmo, ZX_PROP_NAME, 72 SHADOW_VMO_NAME, sizeof(SHADOW_VMO_NAME) - 1); 73 74 status = _zx_vmar_map( 75 shadow_vmar, 76 ZX_VM_SPECIFIC | ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 77 shadow_shadow_size - info.base, vmo, 0, shadow_used_size, &shadow_addr); 78 if (status != ZX_OK || shadow_addr != shadow_shadow_size) 79 __builtin_trap(); 80 81 status = _zx_handle_close(vmo); 82 if (status != ZX_OK) 83 __builtin_trap(); 84 85 // Drop the VMAR handle. 86 // The mappings in the shadow region can never be changed. 87 status = _zx_handle_close(shadow_vmar); 88 if (status != ZX_OK) 89 __builtin_trap(); 90 91 // Store the values to be exported to the sanitizer runtime library. 92 shadow_bounds.shadow_base = shadow_shadow_size; 93 shadow_bounds.shadow_limit = shadow_virtual_size; 94 shadow_bounds.memory_limit = top; 95 96 // There's nothing here that the compiler should think it could move 97 // around much, so this almost certainly doesn't actually do anything. 98 // But the notion is that after this point, it's OK to run ASanified 99 // functions whereas before now it wasn't. So doing this expresses 100 // explicitly the intent that everything before here must be well and 101 // truly done before anything after here is safe to run. 102 atomic_signal_fence(memory_order_seq_cst); 103} 104 105sanitizer_shadow_bounds_t __sanitizer_shadow_bounds(void) { 106 return shadow_bounds; 107} 108 109#else 110 111static const char kBadDepsMessage[] = 112 "module compiled with -fsanitize=address loaded in process without it"; 113 114// This should never be called in the unsanitized runtime. 115// But it's still part of the ABI. 116sanitizer_shadow_bounds_t __sanitizer_shadow_bounds(void) { 117 __sanitizer_log_write(kBadDepsMessage, sizeof(kBadDepsMessage) - 1); 118 __builtin_trap(); 119} 120 121#endif // __has_feature(address_sanitizer) 122