Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: base/allocator/allocator_interception_mac.mm

Issue 2676093003: mac: Hook up allocator shim during app startup. (Closed)
Patch Set: Remove unused include. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/allocator/allocator_interception_mac.h ('k') | base/process/memory_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 // This file contains all the logic necessary to intercept allocations on 5 // This file contains all the logic necessary to intercept allocations on
6 // macOS. "malloc zones" are an abstraction that allows the process to intercept 6 // macOS. "malloc zones" are an abstraction that allows the process to intercept
7 // all malloc-related functions. There is no good mechanism [short of 7 // all malloc-related functions. There is no good mechanism [short of
8 // interposition] to determine new malloc zones are added, so there's no clean 8 // interposition] to determine new malloc zones are added, so there's no clean
9 // mechanism to intercept all malloc zones. This file contains logic to 9 // mechanism to intercept all malloc zones. This file contains logic to
10 // intercept the default and purgeable zones, which always exist. A cursory 10 // intercept the default and purgeable zones, which always exist. A cursory
11 // review of Chrome seems to imply that non-default zones are almost never used. 11 // review of Chrome seems to imply that non-default zones are almost never used.
12 // 12 //
13 // This file also contains logic to intercept Core Foundation and Objective-C 13 // This file also contains logic to intercept Core Foundation and Objective-C
14 // allocations. The implementations forward to the default malloc zone, so the 14 // allocations. The implementations forward to the default malloc zone, so the
15 // only reason to intercept these calls is to re-label OOM crashes with slightly 15 // only reason to intercept these calls is to re-label OOM crashes with slightly
16 // more details. 16 // more details.
17 17
18 #include "base/allocator/allocator_interception_mac.h" 18 #include "base/allocator/allocator_interception_mac.h"
19 19
20 #include <CoreFoundation/CoreFoundation.h> 20 #include <CoreFoundation/CoreFoundation.h>
21 #import <Foundation/Foundation.h> 21 #import <Foundation/Foundation.h>
22 #include <errno.h> 22 #include <errno.h>
23 #include <mach/mach.h> 23 #include <mach/mach.h>
24 #include <mach/mach_vm.h> 24 #include <mach/mach_vm.h>
25 #import <objc/runtime.h> 25 #import <objc/runtime.h>
26 #include <stddef.h> 26 #include <stddef.h>
27 27
28 #include <new> 28 #include <new>
29 29
30 #include "base/allocator/allocator_shim.h"
31 #include "base/allocator/features.h"
30 #include "base/logging.h" 32 #include "base/logging.h"
31 #include "base/mac/mac_util.h" 33 #include "base/mac/mac_util.h"
32 #include "base/mac/mach_logging.h" 34 #include "base/mac/mach_logging.h"
33 #include "base/process/memory.h" 35 #include "base/process/memory.h"
34 #include "base/scoped_clear_errno.h" 36 #include "base/scoped_clear_errno.h"
35 #include "build/build_config.h" 37 #include "build/build_config.h"
36 #include "third_party/apple_apsl/CFBase.h" 38 #include "third_party/apple_apsl/CFBase.h"
37 39
38 namespace base { 40 namespace base {
39 namespace allocator { 41 namespace allocator {
40 42
43 bool g_replaced_default_zone = false;
44
41 MallocZoneFunctions::MallocZoneFunctions() {} 45 MallocZoneFunctions::MallocZoneFunctions() {}
42 46
43 namespace { 47 namespace {
44 48
45 bool g_oom_killer_enabled; 49 bool g_oom_killer_enabled;
46 bool g_replaced_default_zone = false;
47 50
48 // Starting with Mac OS X 10.7, the zone allocators set up by the system are 51 // Starting with Mac OS X 10.7, the zone allocators set up by the system are
49 // read-only, to prevent them from being overwritten in an attack. However, 52 // read-only, to prevent them from being overwritten in an attack. However,
50 // blindly unprotecting and reprotecting the zone allocators fails with 53 // blindly unprotecting and reprotecting the zone allocators fails with
51 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of 54 // GuardMalloc because GuardMalloc sets up its zone allocator using a block of
52 // memory in its bss. Explicit saving/restoring of the protection is required. 55 // memory in its bss. Explicit saving/restoring of the protection is required.
53 // 56 //
54 // This function takes a pointer to a malloc zone, de-protects it if necessary, 57 // This function takes a pointer to a malloc zone, de-protects it if necessary,
55 // and returns (in the out parameters) a region of memory (if any) to be 58 // and returns (in the out parameters) a region of memory (if any) to be
56 // re-protected when modifications are complete. This approach assumes that 59 // re-protected when modifications are complete. This approach assumes that
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). 199 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ).
197 if (!result && size && alignment >= sizeof(void*) && 200 if (!result && size && alignment >= sizeof(void*) &&
198 (alignment & (alignment - 1)) == 0) { 201 (alignment & (alignment - 1)) == 0) {
199 TerminateBecauseOutOfMemory(size); 202 TerminateBecauseOutOfMemory(size);
200 } 203 }
201 return result; 204 return result;
202 } 205 }
203 206
204 #endif // !defined(ADDRESS_SANITIZER) 207 #endif // !defined(ADDRESS_SANITIZER)
205 208
206 // === C++ operator new ===
207
208 void oom_killer_new() {
209 TerminateBecauseOutOfMemory(0);
210 }
211
212 #if !defined(ADDRESS_SANITIZER) 209 #if !defined(ADDRESS_SANITIZER)
213 210
214 // === Core Foundation CFAllocators === 211 // === Core Foundation CFAllocators ===
215 212
216 bool CanGetContextForCFAllocator() { 213 bool CanGetContextForCFAllocator() {
217 return !base::mac::IsOSLaterThan10_12_DontCallThis(); 214 return !base::mac::IsOSLaterThan10_12_DontCallThis();
218 } 215 }
219 216
220 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { 217 CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) {
221 ChromeCFAllocatorLions* our_allocator = const_cast<ChromeCFAllocatorLions*>( 218 ChromeCFAllocatorLions* our_allocator = const_cast<ChromeCFAllocatorLions*>(
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 // due to these other factors, or due to genuine memory or address space 431 // due to these other factors, or due to genuine memory or address space
435 // exhaustion. The fact that it only allocates space from the "tiny" free list 432 // exhaustion. The fact that it only allocates space from the "tiny" free list
436 // means that it's likely that a failure will not be due to memory exhaustion. 433 // means that it's likely that a failure will not be due to memory exhaustion.
437 // Similarly, these constraints on batch_malloc mean that callers must always 434 // Similarly, these constraints on batch_malloc mean that callers must always
438 // be expecting to receive less memory than was requested, even in situations 435 // be expecting to receive less memory than was requested, even in situations
439 // where memory pressure is not a concern. Finally, the only public interface 436 // where memory pressure is not a concern. Finally, the only public interface
440 // to batch_malloc is malloc_zone_batch_malloc, which is specific to the 437 // to batch_malloc is malloc_zone_batch_malloc, which is specific to the
441 // system's malloc implementation. It's unlikely that anyone's even heard of 438 // system's malloc implementation. It's unlikely that anyone's even heard of
442 // it. 439 // it.
443 440
444 // === C++ operator new ===
445
446 // Yes, operator new does call through to malloc, but this will catch failures
447 // that our imperfect handling of malloc cannot.
448
449 std::set_new_handler(oom_killer_new);
450
451 #ifndef ADDRESS_SANITIZER 441 #ifndef ADDRESS_SANITIZER
452 // === Core Foundation CFAllocators === 442 // === Core Foundation CFAllocators ===
453 443
454 // This will not catch allocation done by custom allocators, but will catch 444 // This will not catch allocation done by custom allocators, but will catch
455 // all allocation done by system-provided ones. 445 // all allocation done by system-provided ones.
456 446
457 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && 447 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc &&
458 !g_old_cfallocator_malloc_zone) 448 !g_old_cfallocator_malloc_zone)
459 << "Old allocators unexpectedly non-null"; 449 << "Old allocators unexpectedly non-null";
460 450
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 g_old_allocWithZone = 492 g_old_allocWithZone =
503 reinterpret_cast<allocWithZone_t>(method_getImplementation(orig_method)); 493 reinterpret_cast<allocWithZone_t>(method_getImplementation(orig_method));
504 CHECK(g_old_allocWithZone) 494 CHECK(g_old_allocWithZone)
505 << "Failed to get allocWithZone allocation function."; 495 << "Failed to get allocWithZone allocation function.";
506 method_setImplementation(orig_method, 496 method_setImplementation(orig_method,
507 reinterpret_cast<IMP>(oom_killer_allocWithZone)); 497 reinterpret_cast<IMP>(oom_killer_allocWithZone));
508 } 498 }
509 499
510 } // namespace allocator 500 } // namespace allocator
511 } // namespace base 501 } // namespace base
OLDNEW
« no previous file with comments | « base/allocator/allocator_interception_mac.h ('k') | base/process/memory_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698