1 /* 2 * Copyright (c) 2014, 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_VM_MEMORY_GUARDED_MEMORY_HPP 26 #define SHARE_VM_MEMORY_GUARDED_MEMORY_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 // Private inner classes for memory layout... 86 87 protected: 88 89 /** 90 * Guard class for header and trailer known pattern to test for overwrites. 91 */ 92 class Guard { // Class for raw memory (no vtbl allowed) 93 friend class GuardedMemory; 94 protected: 95 enum { 96 GUARD_SIZE = 16 97 }; 98 99 u_char _guard[GUARD_SIZE]; 100 101 public: 102 103 void build() { 104 u_char* c = _guard; // Possibly unaligned if tail guard 105 u_char* end = c + GUARD_SIZE; 106 while (c < end) { 107 *c = badResourceValue; 108 c++; 109 } 110 } 111 112 bool verify() const { 113 u_char* c = (u_char*) _guard; 114 u_char* end = c + GUARD_SIZE; 115 while (c < end) { 116 if (*c != badResourceValue) { 117 return false; 118 } 119 c++; 120 } 121 return true; 122 } 123 124 }; // GuardedMemory::Guard 125 126 /** 127 * Header guard and size 128 */ 129 class GuardHeader : Guard { 130 friend class GuardedMemory; 131 protected: 132 // Take care in modifying fields here, will effect alignment 133 // e.g. x86 ABI 16 byte stack alignment 134 union { 135 uintptr_t __unused_full_word1; 136 size_t _user_size; 137 }; 138 void* _tag; 139 public: 140 void set_user_size(const size_t usz) { _user_size = usz; } 141 size_t get_user_size() const { return _user_size; } 142 143 void set_tag(const void* tag) { _tag = (void*) tag; } 144 void* get_tag() const { return _tag; } 145 146 }; // GuardedMemory::GuardHeader 147 148 // Guarded Memory... 149 150 protected: 151 u_char* _base_addr; 152 153 public: 154 155 /** 156 * Create new guarded memory. 157 * 158 * Wraps, starting at the given "base_ptr" with guards. Use "get_user_ptr()" 159 * to return a pointer suitable for user data. 160 * 161 * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. 162 * @param user_size the size of the user data to be wrapped. 163 * @param tag optional general purpose tag. 164 */ 165 GuardedMemory(void* base_ptr, const size_t user_size, const void* tag = NULL) { 166 wrap_with_guards(base_ptr, user_size, tag); 167 } 168 169 /** 170 * Wrap existing guarded memory. 171 * 172 * To use this constructor, one must have created guarded memory with 173 * "GuardedMemory(void*, size_t, void*)" (or indirectly via helper, e.g. "wrap_copy()"). 174 * 175 * @param user_p existing wrapped memory. 176 */ 177 GuardedMemory(void* userp) { 178 u_char* user_ptr = (u_char*) userp; 179 assert((uintptr_t)user_ptr > (sizeof(GuardHeader) + 0x1000), "Invalid pointer"); 180 _base_addr = (user_ptr - sizeof(GuardHeader)); 181 } 182 183 /** 184 * Create new guarded memory. 185 * 186 * Wraps, starting at the given "base_ptr" with guards. Allows reuse of stack allocated helper. 187 * 188 * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. 189 * @param user_size the size of the user data to be wrapped. 190 * @param tag optional general purpose tag. 191 * 192 * @return user data pointer (inner pointer to supplied "base_ptr"). 193 */ 194 void* wrap_with_guards(void* base_ptr, size_t user_size, const void* tag = NULL) { 195 assert(base_ptr != NULL, "Attempt to wrap NULL with memory guard"); 196 _base_addr = (u_char*)base_ptr; 197 get_head_guard()->build(); 198 get_head_guard()->set_user_size(user_size); 199 get_tail_guard()->build(); 200 set_tag(tag); 201 set_user_bytes(uninitBlockPad); 202 assert(verify_guards(), "Expected valid memory guards"); 203 return get_user_ptr(); 204 } 205 206 /** 207 * Verify head and tail guards. 208 * 209 * @return true if guards are intact, false would indicate a buffer overrun. 210 */ 211 bool verify_guards() const { 212 if (_base_addr != NULL) { 213 return (get_head_guard()->verify() && get_tail_guard()->verify()); 214 } 215 return false; 216 } 217 218 /** 219 * Set the general purpose tag. 220 * 221 * @param tag general purpose tag. 222 */ 223 void set_tag(const void* tag) { get_head_guard()->set_tag(tag); } 224 225 /** 226 * Return the general purpose tag. 227 * 228 * @return the general purpose tag, defaults to NULL. 229 */ 230 void* get_tag() const { return get_head_guard()->get_tag(); } 231 232 /** 233 * Return the size of the user data. 234 * 235 * @return the size of the user data. 236 */ 237 size_t get_user_size() const { 238 assert(_base_addr, "Not wrapping any memory"); 239 return get_head_guard()->get_user_size(); 240 } 241 242 /** 243 * Return the user data pointer. 244 * 245 * @return the user data pointer. 246 */ 247 u_char* get_user_ptr() const { 248 assert(_base_addr, "Not wrapping any memory"); 249 return _base_addr + sizeof(GuardHeader); 250 } 251 252 /** 253 * Release the wrapped pointer for resource freeing. 254 * 255 * Pads the user data with "freeBlockPad", and dis-associates the helper. 256 * 257 * @return the original base pointer used to wrap the data. 258 */ 259 void* release_for_freeing() { 260 set_user_bytes(freeBlockPad); 261 return release(); 262 } 263 264 /** 265 * Dis-associate the help from the original base address. 266 * 267 * @return the original base pointer used to wrap the data. 268 */ 269 void* release() { 270 void* p = (void*) _base_addr; 271 _base_addr = NULL; 272 return p; 273 } 274 275 virtual void print_on(outputStream* st) const; 276 277 protected: 278 GuardHeader* get_head_guard() const { return (GuardHeader*) _base_addr; } 279 Guard* get_tail_guard() const { return (Guard*) (get_user_ptr() + get_user_size()); }; 280 void set_user_bytes(u_char ch) { 281 memset(get_user_ptr(), ch, get_user_size()); 282 } 283 284 public: 285 /** 286 * Return the total size required for wrapping the given user size. 287 * 288 * @return the total size required for wrapping the given user size. 289 */ 290 static size_t get_total_size(size_t user_size) { 291 size_t total_size = sizeof(GuardHeader) + user_size + sizeof(Guard); 292 assert(total_size > user_size, "Unexpected wrap-around"); 293 return total_size; 294 } 295 296 // Helper functions... 297 298 /** 299 * Wrap a copy of size "len" of "ptr". 300 * 301 * @param ptr the memory to be copied 302 * @param len the length of the copy 303 * @param tag optional general purpose tag (see GuardedMemory::get_tag()) 304 * 305 * @return guarded wrapped memory pointer to the user area, or NULL if OOM. 306 */ 307 static void* wrap_copy(const void* p, const size_t len, const void* tag = NULL); 308 309 /** 310 * Free wrapped copy. 311 * 312 * Frees memory copied with "wrap_copy()". 313 * 314 * @param p memory returned by "wrap_copy()". 315 * 316 * @return true if guards were verified as intact. false indicates a buffer overrun. 317 */ 318 static bool free_copy(void* p); 319 320 // Testing... 321 #ifndef PRODUCT 322 static void test_guarded_memory(void); 323 #endif 324 }; // GuardedMemory 325 326 #endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP