xref: /aosp_15_r20/external/cronet/base/process/memory_linux.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/process/memory.h"
6 
7 #include <stddef.h>
8 
9 #include <new>
10 
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/process/internal_linux.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "build/build_config.h"
18 #include "partition_alloc/partition_alloc_buildflags.h"
19 #include "partition_alloc/shim/allocator_shim.h"
20 
21 #if !BUILDFLAG(USE_ALLOCATOR_SHIM) && \
22     !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && defined(LIBC_GLIBC)
23 extern "C" {
24 void* __libc_malloc(size_t);
25 void __libc_free(void*);
26 }
27 #endif
28 
29 namespace base {
30 
31 namespace {
32 
ReleaseReservationOrTerminate()33 void ReleaseReservationOrTerminate() {
34   if (internal::ReleaseAddressSpaceReservation())
35     return;
36   TerminateBecauseOutOfMemory(0);
37 }
38 
39 }  // namespace
40 
EnableTerminationOnHeapCorruption()41 void EnableTerminationOnHeapCorruption() {
42   // On Linux, there nothing to do AFAIK.
43 }
44 
EnableTerminationOnOutOfMemory()45 void EnableTerminationOnOutOfMemory() {
46   // Set the new-out of memory handler.
47   std::set_new_handler(&ReleaseReservationOrTerminate);
48   // If we're using glibc's allocator, the above functions will override
49   // malloc and friends and make them die on out of memory.
50 
51 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
52   allocator_shim::SetCallNewHandlerOnMallocFailure(true);
53 #endif
54 }
55 
56 // ScopedAllowBlocking() has private constructor and it can only be used in
57 // friend classes/functions. Declaring a class is easier in this situation to
58 // avoid adding more dependency to thread_restrictions.h because of the
59 // parameter used in AdjustOOMScore(). Specifically, ProcessId is a typedef
60 // and we'll need to include another header file in thread_restrictions.h
61 // without the class.
62 class AdjustOOMScoreHelper {
63  public:
64   AdjustOOMScoreHelper() = delete;
65   AdjustOOMScoreHelper(const AdjustOOMScoreHelper&) = delete;
66   AdjustOOMScoreHelper& operator=(const AdjustOOMScoreHelper&) = delete;
67 
68   static bool AdjustOOMScore(ProcessId process, int score);
69 };
70 
71 // static.
AdjustOOMScore(ProcessId process,int score)72 bool AdjustOOMScoreHelper::AdjustOOMScore(ProcessId process, int score) {
73   if (score < 0 || score > kMaxOomScore)
74     return false;
75 
76   FilePath oom_path(internal::GetProcPidDir(process));
77 
78   // Temporarily allowing blocking since oom paths are pseudo-filesystem paths.
79   base::ScopedAllowBlocking allow_blocking;
80 
81   // Attempt to write the newer oom_score_adj file first.
82   FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
83   if (PathExists(oom_file)) {
84     std::string score_str = NumberToString(score);
85     DVLOG(1) << "Adjusting oom_score_adj of " << process << " to "
86              << score_str;
87     int score_len = static_cast<int>(score_str.length());
88     return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
89   }
90 
91   // If the oom_score_adj file doesn't exist, then we write the old
92   // style file and translate the oom_adj score to the range 0-15.
93   oom_file = oom_path.AppendASCII("oom_adj");
94   if (PathExists(oom_file)) {
95     // Max score for the old oom_adj range.  Used for conversion of new
96     // values to old values.
97     const int kMaxOldOomScore = 15;
98 
99     int converted_score = score * kMaxOldOomScore / kMaxOomScore;
100     std::string score_str = NumberToString(converted_score);
101     DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
102     int score_len = static_cast<int>(score_str.length());
103     return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
104   }
105 
106   return false;
107 }
108 
109 // NOTE: This is not the only version of this function in the source:
110 // the setuid sandbox (in process_util_linux.c, in the sandbox source)
111 // also has its own C version.
AdjustOOMScore(ProcessId process,int score)112 bool AdjustOOMScore(ProcessId process, int score) {
113   return AdjustOOMScoreHelper::AdjustOOMScore(process, score);
114 }
115 
UncheckedMalloc(size_t size,void ** result)116 bool UncheckedMalloc(size_t size, void** result) {
117 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
118   *result = allocator_shim::UncheckedAlloc(size);
119 #elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || !defined(LIBC_GLIBC)
120   *result = malloc(size);
121 #elif defined(LIBC_GLIBC)
122   *result = __libc_malloc(size);
123 #endif
124   return *result != nullptr;
125 }
126 
UncheckedFree(void * ptr)127 void UncheckedFree(void* ptr) {
128 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
129   allocator_shim::UncheckedFree(ptr);
130 #elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || !defined(LIBC_GLIBC)
131   free(ptr);
132 #elif defined(LIBC_GLIBC)
133   __libc_free(ptr);
134 #endif
135 }
136 
137 }  // namespace base
138