Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/process/memory.h" | 5 #include "base/process/memory.h" |
| 6 | 6 |
| 7 // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc | |
| 8 // system automatically abort()s on heap corruption. | |
| 9 #if !defined(ADDRESS_SANITIZER) && ARCH_CPU_32_BITS | |
| 10 #define HANDLE_MEMORY_CORRUPTION_MANUALLY | |
| 11 #endif | |
| 12 | |
| 7 #include <CoreFoundation/CoreFoundation.h> | 13 #include <CoreFoundation/CoreFoundation.h> |
| 8 #include <errno.h> | 14 #include <errno.h> |
| 9 #include <mach/mach.h> | 15 #include <mach/mach.h> |
| 10 #include <mach/mach_vm.h> | 16 #include <mach/mach_vm.h> |
| 11 #include <malloc/malloc.h> | 17 #include <malloc/malloc.h> |
| 12 #import <objc/runtime.h> | 18 #import <objc/runtime.h> |
| 13 | 19 |
| 14 #include <new> | 20 #include <new> |
| 15 | 21 |
| 16 #include "base/lazy_instance.h" | 22 #include "base/lazy_instance.h" |
| 17 #include "base/logging.h" | 23 #include "base/logging.h" |
| 18 #include "base/mac/mac_util.h" | 24 #include "base/mac/mac_util.h" |
| 19 #include "base/mac/mach_logging.h" | 25 #include "base/mac/mach_logging.h" |
| 20 #include "base/scoped_clear_errno.h" | 26 #include "base/scoped_clear_errno.h" |
| 21 #include "third_party/apple_apsl/CFBase.h" | 27 #include "third_party/apple_apsl/CFBase.h" |
| 22 #include "third_party/apple_apsl/malloc.h" | 28 #include "third_party/apple_apsl/malloc.h" |
| 23 | 29 |
| 24 #if ARCH_CPU_32_BITS | 30 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 25 #include <dlfcn.h> | 31 #include <dlfcn.h> |
| 26 #include <mach-o/nlist.h> | 32 #include <mach-o/nlist.h> |
| 27 | 33 |
| 28 #include "base/threading/thread_local.h" | 34 #include "base/threading/thread_local.h" |
| 29 #include "third_party/mach_override/mach_override.h" | 35 #include "third_party/mach_override/mach_override.h" |
| 30 #endif // ARCH_CPU_32_BITS | 36 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 31 | 37 |
| 32 namespace base { | 38 namespace base { |
| 33 | 39 |
| 34 // These are helpers for EnableTerminationOnHeapCorruption, which is a no-op | 40 // These are helpers for EnableTerminationOnHeapCorruption, which is a no-op |
| 35 // on 64 bit Macs. | 41 // on 64 bit Macs. |
| 36 #if ARCH_CPU_32_BITS | 42 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 37 namespace { | 43 namespace { |
| 38 | 44 |
| 39 // Finds the library path for malloc() and thus the libC part of libSystem, | 45 // Finds the library path for malloc() and thus the libC part of libSystem, |
| 40 // which in Lion is in a separate image. | 46 // which in Lion is in a separate image. |
| 41 const char* LookUpLibCPath() { | 47 const char* LookUpLibCPath() { |
| 42 const void* addr = reinterpret_cast<void*>(&malloc); | 48 const void* addr = reinterpret_cast<void*>(&malloc); |
| 43 | 49 |
| 44 Dl_info info; | 50 Dl_info info; |
| 45 if (dladdr(addr, &info)) | 51 if (dladdr(addr, &info)) |
| 46 return info.dli_fname; | 52 return info.dli_fname; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 // crash dump info (setting a breakpad key would re-enter the malloc | 161 // crash dump info (setting a breakpad key would re-enter the malloc |
| 156 // library). Max documented errno in intro(2) is actually 102, but | 162 // library). Max documented errno in intro(2) is actually 102, but |
| 157 // it really just needs to be "small" to stay on the right vm page. | 163 // it really just needs to be "small" to stay on the right vm page. |
| 158 const int kMaxErrno = 256; | 164 const int kMaxErrno = 256; |
| 159 char* volatile death_ptr = NULL; | 165 char* volatile death_ptr = NULL; |
| 160 death_ptr += std::min(errno, kMaxErrno); | 166 death_ptr += std::min(errno, kMaxErrno); |
| 161 *death_ptr = '!'; | 167 *death_ptr = '!'; |
| 162 } | 168 } |
| 163 | 169 |
| 164 } // namespace | 170 } // namespace |
| 165 #endif // ARCH_CPU_32_BITS | 171 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 166 | 172 |
| 167 void EnableTerminationOnHeapCorruption() { | 173 void EnableTerminationOnHeapCorruption() { |
| 168 #if defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS | 174 #if !defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
|
Nico
2014/07/16 19:34:24
Since the comment that used to be here is now at t
tzik
2014/07/17 08:17:27
Done.
| |
| 169 // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc | |
| 170 // system automatically abort()s on heap corruption. | |
| 171 return; | 175 return; |
| 172 #else | 176 #else |
| 173 // Only override once, otherwise CrMallocErrorBreak() will recurse | 177 // Only override once, otherwise CrMallocErrorBreak() will recurse |
| 174 // to itself. | 178 // to itself. |
| 175 if (g_original_malloc_error_break) | 179 if (g_original_malloc_error_break) |
| 176 return; | 180 return; |
| 177 | 181 |
| 178 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); | 182 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); |
| 179 if (!malloc_error_break) { | 183 if (!malloc_error_break) { |
| 180 DLOG(WARNING) << "Could not find malloc_error_break"; | 184 DLOG(WARNING) << "Could not find malloc_error_break"; |
| 181 return; | 185 return; |
| 182 } | 186 } |
| 183 | 187 |
| 184 mach_error_t err = mach_override_ptr( | 188 mach_error_t err = mach_override_ptr( |
| 185 (void*)malloc_error_break, | 189 (void*)malloc_error_break, |
| 186 (void*)&CrMallocErrorBreak, | 190 (void*)&CrMallocErrorBreak, |
| 187 (void**)&g_original_malloc_error_break); | 191 (void**)&g_original_malloc_error_break); |
| 188 | 192 |
| 189 if (err != err_none) | 193 if (err != err_none) |
| 190 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; | 194 DLOG(WARNING) << "Could not override malloc_error_break; error = " << err; |
| 191 #endif // defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS | 195 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 192 } | 196 } |
| 193 | 197 |
| 194 // ------------------------------------------------------------------------ | 198 // ------------------------------------------------------------------------ |
| 195 | 199 |
| 196 namespace { | 200 namespace { |
| 197 | 201 |
| 198 bool g_oom_killer_enabled; | 202 bool g_oom_killer_enabled; |
| 199 | 203 |
| 204 #if !defined(ADDRESS_SANITIZER) | |
| 205 | |
| 200 // Starting with Mac OS X 10.7, the zone allocators set up by the system are | 206 // Starting with Mac OS X 10.7, the zone allocators set up by the system are |
| 201 // read-only, to prevent them from being overwritten in an attack. However, | 207 // read-only, to prevent them from being overwritten in an attack. However, |
| 202 // blindly unprotecting and reprotecting the zone allocators fails with | 208 // blindly unprotecting and reprotecting the zone allocators fails with |
| 203 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of | 209 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of |
| 204 // memory in its bss. Explicit saving/restoring of the protection is required. | 210 // memory in its bss. Explicit saving/restoring of the protection is required. |
| 205 // | 211 // |
| 206 // This function takes a pointer to a malloc zone, de-protects it if necessary, | 212 // This function takes a pointer to a malloc zone, de-protects it if necessary, |
| 207 // and returns (in the out parameters) a region of memory (if any) to be | 213 // and returns (in the out parameters) a region of memory (if any) to be |
| 208 // re-protected when modifications are complete. This approach assumes that | 214 // re-protected when modifications are complete. This approach assumes that |
| 209 // there is no contention for the protection of this memory. | 215 // there is no contention for the protection of this memory. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 | 288 |
| 283 malloc_type g_old_malloc_purgeable; | 289 malloc_type g_old_malloc_purgeable; |
| 284 calloc_type g_old_calloc_purgeable; | 290 calloc_type g_old_calloc_purgeable; |
| 285 valloc_type g_old_valloc_purgeable; | 291 valloc_type g_old_valloc_purgeable; |
| 286 free_type g_old_free_purgeable; | 292 free_type g_old_free_purgeable; |
| 287 realloc_type g_old_realloc_purgeable; | 293 realloc_type g_old_realloc_purgeable; |
| 288 memalign_type g_old_memalign_purgeable; | 294 memalign_type g_old_memalign_purgeable; |
| 289 | 295 |
| 290 void* oom_killer_malloc(struct _malloc_zone_t* zone, | 296 void* oom_killer_malloc(struct _malloc_zone_t* zone, |
| 291 size_t size) { | 297 size_t size) { |
| 292 #if ARCH_CPU_32_BITS | 298 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 293 ScopedClearErrno clear_errno; | 299 ScopedClearErrno clear_errno; |
| 294 #endif // ARCH_CPU_32_BITS | 300 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 295 void* result = g_old_malloc(zone, size); | 301 void* result = g_old_malloc(zone, size); |
| 296 if (!result && size) | 302 if (!result && size) |
| 297 debug::BreakDebugger(); | 303 debug::BreakDebugger(); |
| 298 return result; | 304 return result; |
| 299 } | 305 } |
| 300 | 306 |
| 301 void* oom_killer_calloc(struct _malloc_zone_t* zone, | 307 void* oom_killer_calloc(struct _malloc_zone_t* zone, |
| 302 size_t num_items, | 308 size_t num_items, |
| 303 size_t size) { | 309 size_t size) { |
| 304 #if ARCH_CPU_32_BITS | 310 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 305 ScopedClearErrno clear_errno; | 311 ScopedClearErrno clear_errno; |
| 306 #endif // ARCH_CPU_32_BITS | 312 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 307 void* result = g_old_calloc(zone, num_items, size); | 313 void* result = g_old_calloc(zone, num_items, size); |
| 308 if (!result && num_items && size) | 314 if (!result && num_items && size) |
| 309 debug::BreakDebugger(); | 315 debug::BreakDebugger(); |
| 310 return result; | 316 return result; |
| 311 } | 317 } |
| 312 | 318 |
| 313 void* oom_killer_valloc(struct _malloc_zone_t* zone, | 319 void* oom_killer_valloc(struct _malloc_zone_t* zone, |
| 314 size_t size) { | 320 size_t size) { |
| 315 #if ARCH_CPU_32_BITS | 321 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 316 ScopedClearErrno clear_errno; | 322 ScopedClearErrno clear_errno; |
| 317 #endif // ARCH_CPU_32_BITS | 323 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 318 void* result = g_old_valloc(zone, size); | 324 void* result = g_old_valloc(zone, size); |
| 319 if (!result && size) | 325 if (!result && size) |
| 320 debug::BreakDebugger(); | 326 debug::BreakDebugger(); |
| 321 return result; | 327 return result; |
| 322 } | 328 } |
| 323 | 329 |
| 324 void oom_killer_free(struct _malloc_zone_t* zone, | 330 void oom_killer_free(struct _malloc_zone_t* zone, |
| 325 void* ptr) { | 331 void* ptr) { |
| 326 #if ARCH_CPU_32_BITS | 332 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 327 ScopedClearErrno clear_errno; | 333 ScopedClearErrno clear_errno; |
| 328 #endif // ARCH_CPU_32_BITS | 334 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 329 g_old_free(zone, ptr); | 335 g_old_free(zone, ptr); |
| 330 } | 336 } |
| 331 | 337 |
| 332 void* oom_killer_realloc(struct _malloc_zone_t* zone, | 338 void* oom_killer_realloc(struct _malloc_zone_t* zone, |
| 333 void* ptr, | 339 void* ptr, |
| 334 size_t size) { | 340 size_t size) { |
| 335 #if ARCH_CPU_32_BITS | 341 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 336 ScopedClearErrno clear_errno; | 342 ScopedClearErrno clear_errno; |
| 337 #endif // ARCH_CPU_32_BITS | 343 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 338 void* result = g_old_realloc(zone, ptr, size); | 344 void* result = g_old_realloc(zone, ptr, size); |
| 339 if (!result && size) | 345 if (!result && size) |
| 340 debug::BreakDebugger(); | 346 debug::BreakDebugger(); |
| 341 return result; | 347 return result; |
| 342 } | 348 } |
| 343 | 349 |
| 344 void* oom_killer_memalign(struct _malloc_zone_t* zone, | 350 void* oom_killer_memalign(struct _malloc_zone_t* zone, |
| 345 size_t alignment, | 351 size_t alignment, |
| 346 size_t size) { | 352 size_t size) { |
| 347 #if ARCH_CPU_32_BITS | 353 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 348 ScopedClearErrno clear_errno; | 354 ScopedClearErrno clear_errno; |
| 349 #endif // ARCH_CPU_32_BITS | 355 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 350 void* result = g_old_memalign(zone, alignment, size); | 356 void* result = g_old_memalign(zone, alignment, size); |
| 351 // Only die if posix_memalign would have returned ENOMEM, since there are | 357 // Only die if posix_memalign would have returned ENOMEM, since there are |
| 352 // other reasons why NULL might be returned (see | 358 // other reasons why NULL might be returned (see |
| 353 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 359 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
| 354 if (!result && size && alignment >= sizeof(void*) | 360 if (!result && size && alignment >= sizeof(void*) |
| 355 && (alignment & (alignment - 1)) == 0) { | 361 && (alignment & (alignment - 1)) == 0) { |
| 356 debug::BreakDebugger(); | 362 debug::BreakDebugger(); |
| 357 } | 363 } |
| 358 return result; | 364 return result; |
| 359 } | 365 } |
| 360 | 366 |
| 361 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, | 367 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, |
| 362 size_t size) { | 368 size_t size) { |
| 363 #if ARCH_CPU_32_BITS | 369 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 364 ScopedClearErrno clear_errno; | 370 ScopedClearErrno clear_errno; |
| 365 #endif // ARCH_CPU_32_BITS | 371 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 366 void* result = g_old_malloc_purgeable(zone, size); | 372 void* result = g_old_malloc_purgeable(zone, size); |
| 367 if (!result && size) | 373 if (!result && size) |
| 368 debug::BreakDebugger(); | 374 debug::BreakDebugger(); |
| 369 return result; | 375 return result; |
| 370 } | 376 } |
| 371 | 377 |
| 372 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, | 378 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, |
| 373 size_t num_items, | 379 size_t num_items, |
| 374 size_t size) { | 380 size_t size) { |
| 375 #if ARCH_CPU_32_BITS | 381 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 376 ScopedClearErrno clear_errno; | 382 ScopedClearErrno clear_errno; |
| 377 #endif // ARCH_CPU_32_BITS | 383 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 378 void* result = g_old_calloc_purgeable(zone, num_items, size); | 384 void* result = g_old_calloc_purgeable(zone, num_items, size); |
| 379 if (!result && num_items && size) | 385 if (!result && num_items && size) |
| 380 debug::BreakDebugger(); | 386 debug::BreakDebugger(); |
| 381 return result; | 387 return result; |
| 382 } | 388 } |
| 383 | 389 |
| 384 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, | 390 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, |
| 385 size_t size) { | 391 size_t size) { |
| 386 #if ARCH_CPU_32_BITS | 392 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 387 ScopedClearErrno clear_errno; | 393 ScopedClearErrno clear_errno; |
| 388 #endif // ARCH_CPU_32_BITS | 394 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 389 void* result = g_old_valloc_purgeable(zone, size); | 395 void* result = g_old_valloc_purgeable(zone, size); |
| 390 if (!result && size) | 396 if (!result && size) |
| 391 debug::BreakDebugger(); | 397 debug::BreakDebugger(); |
| 392 return result; | 398 return result; |
| 393 } | 399 } |
| 394 | 400 |
| 395 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, | 401 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, |
| 396 void* ptr) { | 402 void* ptr) { |
| 397 #if ARCH_CPU_32_BITS | 403 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 398 ScopedClearErrno clear_errno; | 404 ScopedClearErrno clear_errno; |
| 399 #endif // ARCH_CPU_32_BITS | 405 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 400 g_old_free_purgeable(zone, ptr); | 406 g_old_free_purgeable(zone, ptr); |
| 401 } | 407 } |
| 402 | 408 |
| 403 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, | 409 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, |
| 404 void* ptr, | 410 void* ptr, |
| 405 size_t size) { | 411 size_t size) { |
| 406 #if ARCH_CPU_32_BITS | 412 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 407 ScopedClearErrno clear_errno; | 413 ScopedClearErrno clear_errno; |
| 408 #endif // ARCH_CPU_32_BITS | 414 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 409 void* result = g_old_realloc_purgeable(zone, ptr, size); | 415 void* result = g_old_realloc_purgeable(zone, ptr, size); |
| 410 if (!result && size) | 416 if (!result && size) |
| 411 debug::BreakDebugger(); | 417 debug::BreakDebugger(); |
| 412 return result; | 418 return result; |
| 413 } | 419 } |
| 414 | 420 |
| 415 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, | 421 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, |
| 416 size_t alignment, | 422 size_t alignment, |
| 417 size_t size) { | 423 size_t size) { |
| 418 #if ARCH_CPU_32_BITS | 424 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 419 ScopedClearErrno clear_errno; | 425 ScopedClearErrno clear_errno; |
| 420 #endif // ARCH_CPU_32_BITS | 426 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 421 void* result = g_old_memalign_purgeable(zone, alignment, size); | 427 void* result = g_old_memalign_purgeable(zone, alignment, size); |
| 422 // Only die if posix_memalign would have returned ENOMEM, since there are | 428 // Only die if posix_memalign would have returned ENOMEM, since there are |
| 423 // other reasons why NULL might be returned (see | 429 // other reasons why NULL might be returned (see |
| 424 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 430 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
| 425 if (!result && size && alignment >= sizeof(void*) | 431 if (!result && size && alignment >= sizeof(void*) |
| 426 && (alignment & (alignment - 1)) == 0) { | 432 && (alignment & (alignment - 1)) == 0) { |
| 427 debug::BreakDebugger(); | 433 debug::BreakDebugger(); |
| 428 } | 434 } |
| 429 return result; | 435 return result; |
| 430 } | 436 } |
| 431 | 437 |
| 438 #endif // !defined(ADDRESS_SANITIZER) | |
| 439 | |
| 432 // === C++ operator new === | 440 // === C++ operator new === |
| 433 | 441 |
| 434 void oom_killer_new() { | 442 void oom_killer_new() { |
| 435 debug::BreakDebugger(); | 443 debug::BreakDebugger(); |
| 436 } | 444 } |
| 437 | 445 |
| 446 #if !defined(ADDRESS_SANITIZER) | |
| 447 | |
| 438 // === Core Foundation CFAllocators === | 448 // === Core Foundation CFAllocators === |
| 439 | 449 |
| 440 bool CanGetContextForCFAllocator() { | 450 bool CanGetContextForCFAllocator() { |
| 441 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); | 451 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); |
| 442 } | 452 } |
| 443 | 453 |
| 444 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { | 454 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { |
| 445 if (base::mac::IsOSSnowLeopard()) { | 455 if (base::mac::IsOSSnowLeopard()) { |
| 446 ChromeCFAllocatorLeopards* our_allocator = | 456 ChromeCFAllocatorLeopards* our_allocator = |
| 447 const_cast<ChromeCFAllocatorLeopards*>( | 457 const_cast<ChromeCFAllocatorLeopards*>( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 | 494 |
| 485 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, | 495 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, |
| 486 CFOptionFlags hint, | 496 CFOptionFlags hint, |
| 487 void* info) { | 497 void* info) { |
| 488 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); | 498 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); |
| 489 if (!result) | 499 if (!result) |
| 490 debug::BreakDebugger(); | 500 debug::BreakDebugger(); |
| 491 return result; | 501 return result; |
| 492 } | 502 } |
| 493 | 503 |
| 504 #endif // !defined(ADDRESS_SANITIZER) | |
| 505 | |
| 494 // === Cocoa NSObject allocation === | 506 // === Cocoa NSObject allocation === |
| 495 | 507 |
| 496 typedef id (*allocWithZone_t)(id, SEL, NSZone*); | 508 typedef id (*allocWithZone_t)(id, SEL, NSZone*); |
| 497 allocWithZone_t g_old_allocWithZone; | 509 allocWithZone_t g_old_allocWithZone; |
| 498 | 510 |
| 499 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) | 511 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
| 500 { | 512 { |
| 501 id result = g_old_allocWithZone(self, _cmd, zone); | 513 id result = g_old_allocWithZone(self, _cmd, zone); |
| 502 if (!result) | 514 if (!result) |
| 503 debug::BreakDebugger(); | 515 debug::BreakDebugger(); |
| 504 return result; | 516 return result; |
| 505 } | 517 } |
| 506 | 518 |
| 507 } // namespace | 519 } // namespace |
| 508 | 520 |
| 509 bool UncheckedMalloc(size_t size, void** result) { | 521 bool UncheckedMalloc(size_t size, void** result) { |
| 522 | |
| 523 #if !defined(ADDRESS_SANITIZER) | |
|
Scott Hess - ex-Googler
2014/07/16 19:53:47
I'd invert this and put the ASAN case closer to th
tzik
2014/07/17 08:17:27
Done.
| |
| 510 if (g_old_malloc) { | 524 if (g_old_malloc) { |
| 511 #if ARCH_CPU_32_BITS | 525 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 512 ScopedClearErrno clear_errno; | 526 ScopedClearErrno clear_errno; |
| 513 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); | 527 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); |
| 514 #endif // ARCH_CPU_32_BITS | 528 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 515 *result = g_old_malloc(malloc_default_zone(), size); | 529 *result = g_old_malloc(malloc_default_zone(), size); |
| 516 } else { | 530 } else { |
| 517 *result = malloc(size); | 531 *result = malloc(size); |
| 518 } | 532 } |
| 533 #else | |
| 534 *result = malloc(size); | |
| 535 #endif // !defined(ADDRESS_SANITIZER) | |
| 519 | 536 |
| 520 return *result != NULL; | 537 return *result != NULL; |
| 521 } | 538 } |
| 522 | 539 |
| 523 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { | 540 bool UncheckedCalloc(size_t num_items, size_t size, void** result) { |
| 524 if (g_old_calloc) { | 541 if (g_old_calloc) { |
| 525 #if ARCH_CPU_32_BITS | 542 #if defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 526 ScopedClearErrno clear_errno; | 543 ScopedClearErrno clear_errno; |
| 527 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); | 544 ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true); |
| 528 #endif // ARCH_CPU_32_BITS | 545 #endif // defined(HANDLE_MEMORY_CORRUPTION_MANUALLY) |
| 529 *result = g_old_calloc(malloc_default_zone(), num_items, size); | 546 *result = g_old_calloc(malloc_default_zone(), num_items, size); |
| 530 } else { | 547 } else { |
| 531 *result = calloc(num_items, size); | 548 *result = calloc(num_items, size); |
| 532 } | 549 } |
| 533 | 550 |
| 534 return *result != NULL; | 551 return *result != NULL; |
| 535 } | 552 } |
| 536 | 553 |
| 537 void* UncheckedMalloc(size_t size) { | 554 void* UncheckedMalloc(size_t size) { |
| 538 void* address; | 555 void* address; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 552 | 569 |
| 553 // === C malloc/calloc/valloc/realloc/posix_memalign === | 570 // === C malloc/calloc/valloc/realloc/posix_memalign === |
| 554 | 571 |
| 555 // This approach is not perfect, as requests for amounts of memory larger than | 572 // This approach is not perfect, as requests for amounts of memory larger than |
| 556 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will | 573 // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will |
| 557 // still fail with a NULL rather than dying (see | 574 // still fail with a NULL rather than dying (see |
| 558 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). | 575 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). |
| 559 // Unfortunately, it's the best we can do. Also note that this does not affect | 576 // Unfortunately, it's the best we can do. Also note that this does not affect |
| 560 // allocations from non-default zones. | 577 // allocations from non-default zones. |
| 561 | 578 |
| 579 #if !defined(ADDRESS_SANITIZER) | |
| 580 // Don't do anything special on OOM for the malloc zones replaced by | |
| 581 // AddressSanitizer, as modifying or protecting them may not work correctly. | |
| 582 | |
| 562 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && | 583 CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && |
| 563 !g_old_memalign) << "Old allocators unexpectedly non-null"; | 584 !g_old_memalign) << "Old allocators unexpectedly non-null"; |
| 564 | 585 |
| 565 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && | 586 CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && |
| 566 !g_old_valloc_purgeable && !g_old_realloc_purgeable && | 587 !g_old_valloc_purgeable && !g_old_realloc_purgeable && |
| 567 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; | 588 !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; |
| 568 | 589 |
| 569 #if !defined(ADDRESS_SANITIZER) | |
| 570 // Don't do anything special on OOM for the malloc zones replaced by | |
| 571 // AddressSanitizer, as modifying or protecting them may not work correctly. | |
| 572 | |
| 573 ChromeMallocZone* default_zone = | 590 ChromeMallocZone* default_zone = |
| 574 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); | 591 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
| 575 ChromeMallocZone* purgeable_zone = | 592 ChromeMallocZone* purgeable_zone = |
| 576 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); | 593 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
| 577 | 594 |
| 578 mach_vm_address_t default_reprotection_start = 0; | 595 mach_vm_address_t default_reprotection_start = 0; |
| 579 mach_vm_size_t default_reprotection_length = 0; | 596 mach_vm_size_t default_reprotection_length = 0; |
| 580 vm_prot_t default_reprotection_value = VM_PROT_NONE; | 597 vm_prot_t default_reprotection_value = VM_PROT_NONE; |
| 581 DeprotectMallocZone(default_zone, | 598 DeprotectMallocZone(default_zone, |
| 582 &default_reprotection_start, | 599 &default_reprotection_start, |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 @selector(allocWithZone:)); | 759 @selector(allocWithZone:)); |
| 743 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 760 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
| 744 method_getImplementation(orig_method)); | 761 method_getImplementation(orig_method)); |
| 745 CHECK(g_old_allocWithZone) | 762 CHECK(g_old_allocWithZone) |
| 746 << "Failed to get allocWithZone allocation function."; | 763 << "Failed to get allocWithZone allocation function."; |
| 747 method_setImplementation(orig_method, | 764 method_setImplementation(orig_method, |
| 748 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 765 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
| 749 } | 766 } |
| 750 | 767 |
| 751 } // namespace base | 768 } // namespace base |
| OLD | NEW |