1*6777b538SAndroid Build Coastguard Worker// Copyright 2013 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker#include "base/process/memory.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker#include <stdlib.h> 8*6777b538SAndroid Build Coastguard Worker#include <new> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker#include "build/build_config.h" 11*6777b538SAndroid Build Coastguard Worker#include "partition_alloc/partition_alloc_buildflags.h" 12*6777b538SAndroid Build Coastguard Worker#include "partition_alloc/shim/allocator_interception_apple.h" 13*6777b538SAndroid Build Coastguard Worker#include "partition_alloc/shim/allocator_shim.h" 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Workernamespace base { 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Workernamespace { 18*6777b538SAndroid Build Coastguard Workervoid oom_killer_new() { 19*6777b538SAndroid Build Coastguard Worker TerminateBecauseOutOfMemory(0); 20*6777b538SAndroid Build Coastguard Worker} 21*6777b538SAndroid Build Coastguard Worker} // namespace 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Workervoid EnableTerminationOnHeapCorruption() { 24*6777b538SAndroid Build Coastguard Worker#if !ARCH_CPU_64_BITS 25*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "EnableTerminationOnHeapCorruption only works on 64-bit"; 26*6777b538SAndroid Build Coastguard Worker#endif 27*6777b538SAndroid Build Coastguard Worker} 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Workerbool UncheckedMalloc(size_t size, void** result) { 30*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 31*6777b538SAndroid Build Coastguard Worker // Unchecked allocations can happen before the default malloc() zone is 32*6777b538SAndroid Build Coastguard Worker // registered. In this case, going straight to the shim may explode, since the 33*6777b538SAndroid Build Coastguard Worker // memory will come from a zone which is unknown to the dispatching code in 34*6777b538SAndroid Build Coastguard Worker // libmalloc. Meaning that if the memory gets free()-d, realloc()-ed, or its 35*6777b538SAndroid Build Coastguard Worker // actual size is queried with malloc_size() *before* we get to register our 36*6777b538SAndroid Build Coastguard Worker // zone, we crash. 37*6777b538SAndroid Build Coastguard Worker // 38*6777b538SAndroid Build Coastguard Worker // The cleanest solution would be to detect it and forbid it, but tests (at 39*6777b538SAndroid Build Coastguard Worker // least) allocate in static constructors. Meaning that this code is 40*6777b538SAndroid Build Coastguard Worker // sufficient to cause a crash: 41*6777b538SAndroid Build Coastguard Worker // 42*6777b538SAndroid Build Coastguard Worker // void* ptr = []() { 43*6777b538SAndroid Build Coastguard Worker // void* ptr; 44*6777b538SAndroid Build Coastguard Worker // bool ok = base::UncheckedMalloc(1000, &ptr); 45*6777b538SAndroid Build Coastguard Worker // CHECK(ok); 46*6777b538SAndroid Build Coastguard Worker // free(ptr); 47*6777b538SAndroid Build Coastguard Worker // }(); 48*6777b538SAndroid Build Coastguard Worker // 49*6777b538SAndroid Build Coastguard Worker // (Our static initializer is supposed to have priority, but it doesn't seem 50*6777b538SAndroid Build Coastguard Worker // to work in practice, at least for MachO). 51*6777b538SAndroid Build Coastguard Worker // 52*6777b538SAndroid Build Coastguard Worker // Since unchecked allocations are rare, let's err on the side of caution. 53*6777b538SAndroid Build Coastguard Worker if (!allocator_shim::IsDefaultAllocatorPartitionRootInitialized()) { 54*6777b538SAndroid Build Coastguard Worker *result = malloc(size); 55*6777b538SAndroid Build Coastguard Worker return *result != nullptr; 56*6777b538SAndroid Build Coastguard Worker } 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker // Unlike use_partition_alloc_as_malloc=false, the default malloc zone is 59*6777b538SAndroid Build Coastguard Worker // replaced with PartitionAlloc, so the allocator shim functions work best. 60*6777b538SAndroid Build Coastguard Worker *result = allocator_shim::UncheckedAlloc(size); 61*6777b538SAndroid Build Coastguard Worker return *result != nullptr; 62*6777b538SAndroid Build Coastguard Worker#elif BUILDFLAG(USE_ALLOCATOR_SHIM) 63*6777b538SAndroid Build Coastguard Worker return allocator_shim::UncheckedMallocMac(size, result); 64*6777b538SAndroid Build Coastguard Worker#else // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && 65*6777b538SAndroid Build Coastguard Worker // !BUILDFLAG(USE_ALLOCATOR_SHIM) 66*6777b538SAndroid Build Coastguard Worker *result = malloc(size); 67*6777b538SAndroid Build Coastguard Worker return *result != nullptr; 68*6777b538SAndroid Build Coastguard Worker#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && 69*6777b538SAndroid Build Coastguard Worker // !BUILDFLAG(USE_ALLOCATOR_SHIM) 70*6777b538SAndroid Build Coastguard Worker} 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard Worker// The standard version is defined in memory.cc in case of 73*6777b538SAndroid Build Coastguard Worker// USE_PARTITION_ALLOC_AS_MALLOC. 74*6777b538SAndroid Build Coastguard Worker#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 75*6777b538SAndroid Build Coastguard Workerbool UncheckedCalloc(size_t num_items, size_t size, void** result) { 76*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(USE_ALLOCATOR_SHIM) 77*6777b538SAndroid Build Coastguard Worker return allocator_shim::UncheckedCallocMac(num_items, size, result); 78*6777b538SAndroid Build Coastguard Worker#else 79*6777b538SAndroid Build Coastguard Worker *result = calloc(num_items, size); 80*6777b538SAndroid Build Coastguard Worker return *result != nullptr; 81*6777b538SAndroid Build Coastguard Worker#endif // BUILDFLAG(USE_ALLOCATOR_SHIM) 82*6777b538SAndroid Build Coastguard Worker} 83*6777b538SAndroid Build Coastguard Worker#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Workervoid EnableTerminationOnOutOfMemory() { 86*6777b538SAndroid Build Coastguard Worker // Step 1: Enable OOM killer on C++ failures. 87*6777b538SAndroid Build Coastguard Worker std::set_new_handler(oom_killer_new); 88*6777b538SAndroid Build Coastguard Worker 89*6777b538SAndroid Build Coastguard Worker// Step 2: Enable OOM killer on C-malloc failures for the default zone (if we 90*6777b538SAndroid Build Coastguard Worker// have a shim). 91*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(USE_ALLOCATOR_SHIM) 92*6777b538SAndroid Build Coastguard Worker allocator_shim::SetCallNewHandlerOnMallocFailure(true); 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // Step 3: Enable OOM killer on all other malloc zones (or just "all" without 95*6777b538SAndroid Build Coastguard Worker // "other" if shim is disabled). 96*6777b538SAndroid Build Coastguard Worker allocator_shim::InterceptAllocationsMac(); 97*6777b538SAndroid Build Coastguard Worker#endif // BUILDFLAG(USE_ALLOCATOR_SHIM) 98*6777b538SAndroid Build Coastguard Worker} 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard Workervoid UncheckedFree(void* ptr) { 101*6777b538SAndroid Build Coastguard Worker#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 102*6777b538SAndroid Build Coastguard Worker // Important: might be different from free(), because in some cases, free() 103*6777b538SAndroid Build Coastguard Worker // does not necessarily know about allocator_shim::* functions. 104*6777b538SAndroid Build Coastguard Worker allocator_shim::UncheckedFree(ptr); 105*6777b538SAndroid Build Coastguard Worker#else // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 106*6777b538SAndroid Build Coastguard Worker free(ptr); 107*6777b538SAndroid Build Coastguard Worker#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 108*6777b538SAndroid Build Coastguard Worker} 109*6777b538SAndroid Build Coastguard Worker 110*6777b538SAndroid Build Coastguard Worker} // namespace base 111