xref: /aosp_15_r20/external/cronet/base/process/memory_mac.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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