1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declarations relating to memory intercept functions.
16 : #ifndef SYZYGY_AGENT_ASAN_MEMORY_INTERCEPTORS_H_
17 : #define SYZYGY_AGENT_ASAN_MEMORY_INTERCEPTORS_H_
18 :
19 : #include "base/callback.h"
20 :
21 m : namespace agent {
22 m : namespace asan {
23 :
24 m : class Shadow;
25 :
26 : // Configures the shadow memory to be used by the memory interceptors.
27 : // @param shadow The shadow memory to use. May be null, effectively
28 : // disabling the string interceptors.
29 : // @returns the previously configured shadow memory.
30 : // @note This only updates uses of the shadow via the Shadow API. Interceptors
31 : // that make direct reference to the shadow memory must be patched in
32 : // place using 'PatchMemoryInterceptorShadowReferences'.
33 m : Shadow* SetMemoryInterceptorShadow(Shadow* shadow);
34 :
35 : // Memory accessor mode select.
36 m : enum MemoryAccessorMode {
37 m : MEMORY_ACCESSOR_MODE_NOOP, // Noop mode - no checking performed.
38 m : MEMORY_ACCESSOR_MODE_2G, // 2G address space mode
39 m : MEMORY_ACCESSOR_MODE_4G, // 4G address space mode
40 m : MEMORY_ACCESSOR_MODE_MAX, // This must be last.
41 m : };
42 :
43 : // Type of the callback invoked on entry to the redirector stub. This is
44 : // invoked any time a redirector stub is invoked. The intent is for this
45 : // callback to reach back and patch the caller's import address table to the
46 : // correct memory accessors.
47 : // @param caller_address the return address for this invocation, allows
48 : // identifying the caller's module.
49 : // @returns the selected memory accessor mode.
50 : // @note it's possible to get calls to this callback on multiple threads
51 : // concurrently, whether from a single or multiple modules. The
52 : // implementation therefore may find the IAT in question already patched.
53 m : using RedirectEntryCallback =
54 m : base::Callback<MemoryAccessorMode(const void* caller_address)>;
55 :
56 : // Sets the callback invoked on entry to a redirect stub.
57 m : void SetRedirectEntryCallback(const RedirectEntryCallback& callback);
58 :
59 : // This type is not accurate, as the memory accessors have a custom calling
60 : // convention, but it's nice to have a type for them.
61 m : typedef void (*MemoryAccessorFunction)();
62 :
63 m : struct MemoryAccessorVariants {
64 : // Canonical name of the exported function, e.g. asan_XXX.
65 m : const char* name;
66 m : MemoryAccessorFunction redirect_accessor;
67 m : union {
68 m : struct {
69 : // The MemoryAccessorMode enumeration and the following list must remain
70 : // in sync.
71 m : MemoryAccessorFunction accessor_noop;
72 m : MemoryAccessorFunction accessor_2G;
73 m : MemoryAccessorFunction accessor_4G;
74 m : };
75 m : MemoryAccessorFunction accessors[MEMORY_ACCESSOR_MODE_MAX];
76 m : };
77 m : };
78 m : static_assert(sizeof(MemoryAccessorVariants) == 5 * sizeof(uintptr_t),
79 m : "MemoryAccessorVariants definition is out of sync");
80 :
81 m : extern const MemoryAccessorVariants kMemoryAccessorVariants[];
82 m : extern const size_t kNumMemoryAccessorVariants;
83 :
84 : // List of the memory accessor function variants this file implements.
85 : #define ASAN_MEM_INTERCEPT_FUNCTIONS(F) \
86 m : F(1, read_access, AsanReadAccess) \
87 m : F(2, read_access, AsanReadAccess) \
88 m : F(4, read_access, AsanReadAccess) \
89 m : F(8, read_access, AsanReadAccess) \
90 m : F(10, read_access, AsanReadAccess) \
91 m : F(16, read_access, AsanReadAccess) \
92 m : F(32, read_access, AsanReadAccess) \
93 m : F(1, write_access, AsanWriteAccess) \
94 m : F(2, write_access, AsanWriteAccess) \
95 m : F(4, write_access, AsanWriteAccess) \
96 m : F(8, write_access, AsanWriteAccess) \
97 m : F(10, write_access, AsanWriteAccess) \
98 m : F(16, write_access, AsanWriteAccess) \
99 m : F(32, write_access, AsanWriteAccess)
100 :
101 : #define ASAN_STRING_INTERCEPT_FUNCTIONS(F) \
102 m : F(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 4, 1) \
103 m : F(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 2, 1) \
104 m : F(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 1, 1) \
105 m : F(cmps, _, 1, AsanReadAccess, AsanReadAccess, 4, 1) \
106 m : F(cmps, _, 1, AsanReadAccess, AsanReadAccess, 2, 1) \
107 m : F(cmps, _, 1, AsanReadAccess, AsanReadAccess, 1, 1) \
108 m : F(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 4, 0) \
109 m : F(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 2, 0) \
110 m : F(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 1, 0) \
111 m : F(movs, _, 1, AsanWriteAccess, AsanReadAccess, 4, 0) \
112 m : F(movs, _, 1, AsanWriteAccess, AsanReadAccess, 2, 0) \
113 m : F(movs, _, 1, AsanWriteAccess, AsanReadAccess, 1, 0) \
114 m : F(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 4, 0) \
115 m : F(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 2, 0) \
116 m : F(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 1, 0) \
117 m : F(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 4, 0) \
118 m : F(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 2, 0) \
119 m : F(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 1, 0)
120 :
121 m : } // namespace asan
122 m : } // namespace agent
123 :
124 m : extern "C" {
125 :
126 : // The no-op memory access checker.
127 m : void asan_no_check();
128 :
129 : // The no-op string instruction memory access checker.
130 m : void asan_string_no_check();
131 :
132 : // The table containing the array of shadow memory references. This is made
133 : // visible so that it can be used by the memory interceptor patcher. The table
134 : // itself will not be modified, but the pointers it points to will be.
135 m : extern const void* asan_shadow_references[];
136 :
137 : #define DECLARE_MEM_INTERCEPT_FUNCTIONS(access_size, access_mode_str, \
138 m : access_mode_value) \
139 m : void asan_redirect_##access_size##_byte_##access_mode_str(); \
140 m : void asan_check_##access_size##_byte_##access_mode_str##_2gb(); \
141 m : void asan_check_##access_size##_byte_##access_mode_str##_4gb(); \
142 m : void asan_redirect_##access_size##_byte_##access_mode_str##_no_flags(); \
143 m : void asan_check_##access_size##_byte_##access_mode_str##_no_flags_2gb(); \
144 m : void asan_check_##access_size##_byte_##access_mode_str##_no_flags_4gb();
145 :
146 : // Declare all the memory interceptor functions. Note that these functions have
147 : // a custom calling convention, and can't be invoked directly.
148 m : ASAN_MEM_INTERCEPT_FUNCTIONS(DECLARE_MEM_INTERCEPT_FUNCTIONS)
149 :
150 : #undef DECLARE_MEM_INTERCEPT_FUNCTIONS
151 :
152 : #define DECLARE_STRING_INTERCEPT_FUNCTIONS(func, prefix, counter, dst_mode, \
153 m : src_mode, access_size, compare) \
154 m : void asan_redirect ## prefix ## access_size ## _byte_ ## func ## _access(); \
155 m : void asan_check ## prefix ## access_size ## _byte_ ## func ## _access(); \
156 :
157 : // Declare all the string instruction interceptor functions. Note that these
158 : // functions have a custom calling convention, and can't be invoked directly.
159 m : ASAN_STRING_INTERCEPT_FUNCTIONS(DECLARE_STRING_INTERCEPT_FUNCTIONS)
160 :
161 : #undef DECLARE_STRING_INTERCEPT_FUNCTIONS
162 :
163 m : } // extern "C"
164 :
165 : #endif // SYZYGY_AGENT_ASAN_MEMORY_INTERCEPTORS_H_
|