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