1 | /* |
2 | * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_MEMORY_GUARDEDMEMORY_HPP |
26 | #define SHARE_MEMORY_GUARDEDMEMORY_HPP |
27 | |
28 | #include "memory/allocation.hpp" |
29 | #include "utilities/globalDefinitions.hpp" |
30 | |
31 | /** |
32 | * Guarded memory for detecting buffer overrun. |
33 | * |
34 | * Allows allocations to be wrapped with padded bytes of a known byte pattern, |
35 | * that is a "guard". Guard patterns may be verified to detect buffer overruns. |
36 | * |
37 | * Primarily used by "debug malloc" and "checked JNI". |
38 | * |
39 | * Memory layout: |
40 | * |
41 | * |Offset | Content | Description | |
42 | * |------------------------------------------------------------ |
43 | * |base_addr | 0xABABABABABABABAB | Head guard | |
44 | * |+16 | <size_t:user_size> | User data size | |
45 | * |+sizeof(uintptr_t) | <tag> | Tag word | |
46 | * |+sizeof(void*) | 0xF1 <user_data> ( | User data | |
47 | * |+user_size | 0xABABABABABABABAB | Tail guard | |
48 | * ------------------------------------------------------------- |
49 | * |
50 | * Where: |
51 | * - guard padding uses "badResourceValue" (0xAB) |
52 | * - tag word is general purpose |
53 | * - user data |
54 | * -- initially padded with "uninitBlockPad" (0xF1), |
55 | * -- to "freeBlockPad" (0xBA), when freed |
56 | * |
57 | * Usage: |
58 | * |
59 | * * Allocations: one may wrap allocations with guard memory: |
60 | * <code> |
61 | * Thing* alloc_thing() { |
62 | * void* mem = user_alloc_fn(GuardedMemory::get_total_size(sizeof(thing))); |
63 | * GuardedMemory guarded(mem, sizeof(thing)); |
64 | * return (Thing*) guarded.get_user_ptr(); |
65 | * } |
66 | * </code> |
67 | * * Verify: memory guards are still in tact |
68 | * <code> |
69 | * bool verify_thing(Thing* thing) { |
70 | * GuardedMemory guarded((void*)thing); |
71 | * return guarded.verify_guards(); |
72 | * } |
73 | * </code> |
74 | * * Free: one may mark bytes as freed (further debugging support) |
75 | * <code> |
76 | * void free_thing(Thing* thing) { |
77 | * GuardedMemory guarded((void*)thing); |
78 | * assert(guarded.verify_guards(), "Corrupt thing"); |
79 | * user_free_fn(guards.release_for_freeing(); |
80 | * } |
81 | * </code> |
82 | */ |
83 | class GuardedMemory : StackObj { // Wrapper on stack |
84 | |
85 | friend class GuardedMemoryTest; |
86 | // Private inner classes for memory layout... |
87 | |
88 | protected: |
89 | |
90 | /** |
91 | * Guard class for header and trailer known pattern to test for overwrites. |
92 | */ |
93 | class Guard { // Class for raw memory (no vtbl allowed) |
94 | friend class GuardedMemory; |
95 | protected: |
96 | enum { |
97 | GUARD_SIZE = 16 |
98 | }; |
99 | |
100 | u_char _guard[GUARD_SIZE]; |
101 | |
102 | public: |
103 | |
104 | void build() { |
105 | u_char* c = _guard; // Possibly unaligned if tail guard |
106 | u_char* end = c + GUARD_SIZE; |
107 | while (c < end) { |
108 | *c = badResourceValue; |
109 | c++; |
110 | } |
111 | } |
112 | |
113 | bool verify() const { |
114 | u_char* c = (u_char*) _guard; |
115 | u_char* end = c + GUARD_SIZE; |
116 | while (c < end) { |
117 | if (*c != badResourceValue) { |
118 | return false; |
119 | } |
120 | c++; |
121 | } |
122 | return true; |
123 | } |
124 | |
125 | }; // GuardedMemory::Guard |
126 | |
127 | /** |
128 | * Header guard and size |
129 | */ |
130 | class : Guard { |
131 | friend class GuardedMemory; |
132 | protected: |
133 | // Take care in modifying fields here, will effect alignment |
134 | // e.g. x86 ABI 16 byte stack alignment |
135 | union { |
136 | uintptr_t ; |
137 | size_t ; |
138 | }; |
139 | void* ; |
140 | public: |
141 | void (const size_t usz) { _user_size = usz; } |
142 | size_t () const { return _user_size; } |
143 | |
144 | void (const void* tag) { _tag = (void*) tag; } |
145 | void* () const { return _tag; } |
146 | |
147 | }; // GuardedMemory::GuardHeader |
148 | |
149 | // Guarded Memory... |
150 | |
151 | protected: |
152 | u_char* _base_addr; |
153 | |
154 | public: |
155 | |
156 | /** |
157 | * Create new guarded memory. |
158 | * |
159 | * Wraps, starting at the given "base_ptr" with guards. Use "get_user_ptr()" |
160 | * to return a pointer suitable for user data. |
161 | * |
162 | * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. |
163 | * @param user_size the size of the user data to be wrapped. |
164 | * @param tag optional general purpose tag. |
165 | */ |
166 | GuardedMemory(void* base_ptr, const size_t user_size, const void* tag = NULL) { |
167 | wrap_with_guards(base_ptr, user_size, tag); |
168 | } |
169 | |
170 | /** |
171 | * Wrap existing guarded memory. |
172 | * |
173 | * To use this constructor, one must have created guarded memory with |
174 | * "GuardedMemory(void*, size_t, void*)" (or indirectly via helper, e.g. "wrap_copy()"). |
175 | * |
176 | * @param user_p existing wrapped memory. |
177 | */ |
178 | GuardedMemory(void* userp) { |
179 | u_char* user_ptr = (u_char*) userp; |
180 | assert((uintptr_t)user_ptr > (sizeof(GuardHeader) + 0x1000), "Invalid pointer" ); |
181 | _base_addr = (user_ptr - sizeof(GuardHeader)); |
182 | } |
183 | |
184 | /** |
185 | * Create new guarded memory. |
186 | * |
187 | * Wraps, starting at the given "base_ptr" with guards. Allows reuse of stack allocated helper. |
188 | * |
189 | * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. |
190 | * @param user_size the size of the user data to be wrapped. |
191 | * @param tag optional general purpose tag. |
192 | * |
193 | * @return user data pointer (inner pointer to supplied "base_ptr"). |
194 | */ |
195 | void* wrap_with_guards(void* base_ptr, size_t user_size, const void* tag = NULL) { |
196 | assert(base_ptr != NULL, "Attempt to wrap NULL with memory guard" ); |
197 | _base_addr = (u_char*)base_ptr; |
198 | get_head_guard()->build(); |
199 | get_head_guard()->set_user_size(user_size); |
200 | get_tail_guard()->build(); |
201 | set_tag(tag); |
202 | set_user_bytes(uninitBlockPad); |
203 | assert(verify_guards(), "Expected valid memory guards" ); |
204 | return get_user_ptr(); |
205 | } |
206 | |
207 | /** |
208 | * Verify head and tail guards. |
209 | * |
210 | * @return true if guards are intact, false would indicate a buffer overrun. |
211 | */ |
212 | bool verify_guards() const { |
213 | if (_base_addr != NULL) { |
214 | return (get_head_guard()->verify() && get_tail_guard()->verify()); |
215 | } |
216 | return false; |
217 | } |
218 | |
219 | /** |
220 | * Set the general purpose tag. |
221 | * |
222 | * @param tag general purpose tag. |
223 | */ |
224 | void set_tag(const void* tag) { get_head_guard()->set_tag(tag); } |
225 | |
226 | /** |
227 | * Return the general purpose tag. |
228 | * |
229 | * @return the general purpose tag, defaults to NULL. |
230 | */ |
231 | void* get_tag() const { return get_head_guard()->get_tag(); } |
232 | |
233 | /** |
234 | * Return the size of the user data. |
235 | * |
236 | * @return the size of the user data. |
237 | */ |
238 | size_t get_user_size() const { |
239 | assert(_base_addr != NULL, "Not wrapping any memory" ); |
240 | return get_head_guard()->get_user_size(); |
241 | } |
242 | |
243 | /** |
244 | * Return the user data pointer. |
245 | * |
246 | * @return the user data pointer. |
247 | */ |
248 | u_char* get_user_ptr() const { |
249 | assert(_base_addr != NULL, "Not wrapping any memory" ); |
250 | return _base_addr + sizeof(GuardHeader); |
251 | } |
252 | |
253 | /** |
254 | * Release the wrapped pointer for resource freeing. |
255 | * |
256 | * Pads the user data with "freeBlockPad", and dis-associates the helper. |
257 | * |
258 | * @return the original base pointer used to wrap the data. |
259 | */ |
260 | void* release_for_freeing() { |
261 | set_user_bytes(freeBlockPad); |
262 | return release(); |
263 | } |
264 | |
265 | /** |
266 | * Dis-associate the help from the original base address. |
267 | * |
268 | * @return the original base pointer used to wrap the data. |
269 | */ |
270 | void* release() { |
271 | void* p = (void*) _base_addr; |
272 | _base_addr = NULL; |
273 | return p; |
274 | } |
275 | |
276 | virtual void print_on(outputStream* st) const; |
277 | |
278 | protected: |
279 | GuardHeader* get_head_guard() const { return (GuardHeader*) _base_addr; } |
280 | Guard* get_tail_guard() const { return (Guard*) (get_user_ptr() + get_user_size()); }; |
281 | void set_user_bytes(u_char ch) { |
282 | memset(get_user_ptr(), ch, get_user_size()); |
283 | } |
284 | |
285 | public: |
286 | /** |
287 | * Return the total size required for wrapping the given user size. |
288 | * |
289 | * @return the total size required for wrapping the given user size. |
290 | */ |
291 | static size_t get_total_size(size_t user_size) { |
292 | size_t total_size = sizeof(GuardHeader) + user_size + sizeof(Guard); |
293 | assert(total_size > user_size, "Unexpected wrap-around" ); |
294 | return total_size; |
295 | } |
296 | |
297 | // Helper functions... |
298 | |
299 | /** |
300 | * Wrap a copy of size "len" of "ptr". |
301 | * |
302 | * @param ptr the memory to be copied |
303 | * @param len the length of the copy |
304 | * @param tag optional general purpose tag (see GuardedMemory::get_tag()) |
305 | * |
306 | * @return guarded wrapped memory pointer to the user area, or NULL if OOM. |
307 | */ |
308 | static void* wrap_copy(const void* p, const size_t len, const void* tag = NULL); |
309 | |
310 | /** |
311 | * Free wrapped copy. |
312 | * |
313 | * Frees memory copied with "wrap_copy()". |
314 | * |
315 | * @param p memory returned by "wrap_copy()". |
316 | * |
317 | * @return true if guards were verified as intact. false indicates a buffer overrun. |
318 | */ |
319 | static bool free_copy(void* p); |
320 | |
321 | }; // GuardedMemory |
322 | |
323 | #endif // SHARE_MEMORY_GUARDEDMEMORY_HPP |
324 | |