- add sources.
[platform/framework/web/crosswalk.git] / src / base / process / memory_linux.cc
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
3 // found in the LICENSE file.
4
5 #include "base/process/memory.h"
6
7 #include <new>
8
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/process/internal_linux.h"
13 #include "base/strings/string_number_conversions.h"
14
15 namespace base {
16
17 size_t g_oom_size = 0U;
18
19 namespace {
20
21 void OnNoMemorySize(size_t size) {
22   g_oom_size = size;
23
24   if (size != 0)
25     LOG(FATAL) << "Out of memory, size = " << size;
26   LOG(FATAL) << "Out of memory.";
27 }
28
29 void OnNoMemory() {
30   OnNoMemorySize(0);
31 }
32
33 }  // namespace
34
35 #if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
36     !defined(THREAD_SANITIZER) && !defined(LEAK_SANITIZER)
37
38 #if defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
39
40 extern "C" {
41 void* __libc_malloc(size_t size);
42 void* __libc_realloc(void* ptr, size_t size);
43 void* __libc_calloc(size_t nmemb, size_t size);
44 void* __libc_valloc(size_t size);
45 void* __libc_pvalloc(size_t size);
46 void* __libc_memalign(size_t alignment, size_t size);
47
48 // Overriding the system memory allocation functions:
49 //
50 // For security reasons, we want malloc failures to be fatal. Too much code
51 // doesn't check for a NULL return value from malloc and unconditionally uses
52 // the resulting pointer. If the first offset that they try to access is
53 // attacker controlled, then the attacker can direct the code to access any
54 // part of memory.
55 //
56 // Thus, we define all the standard malloc functions here and mark them as
57 // visibility 'default'. This means that they replace the malloc functions for
58 // all Chromium code and also for all code in shared libraries. There are tests
59 // for this in process_util_unittest.cc.
60 //
61 // If we are using tcmalloc, then the problem is moot since tcmalloc handles
62 // this for us. Thus this code is in a !defined(USE_TCMALLOC) block.
63 //
64 // If we are testing the binary with AddressSanitizer, we should not
65 // redefine malloc and let AddressSanitizer do it instead.
66 //
67 // We call the real libc functions in this code by using __libc_malloc etc.
68 // Previously we tried using dlsym(RTLD_NEXT, ...) but that failed depending on
69 // the link order. Since ld.so needs calloc during symbol resolution, it
70 // defines its own versions of several of these functions in dl-minimal.c.
71 // Depending on the runtime library order, dlsym ended up giving us those
72 // functions and bad things happened. See crbug.com/31809
73 //
74 // This means that any code which calls __libc_* gets the raw libc versions of
75 // these functions.
76
77 #define DIE_ON_OOM_1(function_name) \
78   void* function_name(size_t) __attribute__ ((visibility("default"))); \
79   \
80   void* function_name(size_t size) { \
81     void* ret = __libc_##function_name(size); \
82     if (ret == NULL && size != 0) \
83       OnNoMemorySize(size); \
84     return ret; \
85   }
86
87 #define DIE_ON_OOM_2(function_name, arg1_type) \
88   void* function_name(arg1_type, size_t) \
89       __attribute__ ((visibility("default"))); \
90   \
91   void* function_name(arg1_type arg1, size_t size) { \
92     void* ret = __libc_##function_name(arg1, size); \
93     if (ret == NULL && size != 0) \
94       OnNoMemorySize(size); \
95     return ret; \
96   }
97
98 DIE_ON_OOM_1(malloc)
99 DIE_ON_OOM_1(valloc)
100 DIE_ON_OOM_1(pvalloc)
101
102 DIE_ON_OOM_2(calloc, size_t)
103 DIE_ON_OOM_2(realloc, void*)
104 DIE_ON_OOM_2(memalign, size_t)
105
106 // posix_memalign has a unique signature and doesn't have a __libc_ variant.
107 int posix_memalign(void** ptr, size_t alignment, size_t size)
108     __attribute__ ((visibility("default")));
109
110 int posix_memalign(void** ptr, size_t alignment, size_t size) {
111   // This will use the safe version of memalign, above.
112   *ptr = memalign(alignment, size);
113   return 0;
114 }
115
116 }  // extern C
117
118 #else
119
120 // TODO(mostynb@opera.com): dlsym dance
121
122 #endif  // LIBC_GLIBC && !USE_TCMALLOC
123
124 #endif  // !*_SANITIZER
125
126 void EnableTerminationOnHeapCorruption() {
127   // On Linux, there nothing to do AFAIK.
128 }
129
130 void EnableTerminationOnOutOfMemory() {
131 #if defined(OS_ANDROID)
132   // Android doesn't support setting a new handler.
133   DLOG(WARNING) << "Not feasible.";
134 #else
135   // Set the new-out of memory handler.
136   std::set_new_handler(&OnNoMemory);
137   // If we're using glibc's allocator, the above functions will override
138   // malloc and friends and make them die on out of memory.
139 #endif
140 }
141
142 // NOTE: This is not the only version of this function in the source:
143 // the setuid sandbox (in process_util_linux.c, in the sandbox source)
144 // also has its own C version.
145 bool AdjustOOMScore(ProcessId process, int score) {
146   if (score < 0 || score > kMaxOomScore)
147     return false;
148
149   FilePath oom_path(internal::GetProcPidDir(process));
150
151   // Attempt to write the newer oom_score_adj file first.
152   FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
153   if (PathExists(oom_file)) {
154     std::string score_str = IntToString(score);
155     DVLOG(1) << "Adjusting oom_score_adj of " << process << " to "
156              << score_str;
157     int score_len = static_cast<int>(score_str.length());
158     return (score_len == file_util::WriteFile(oom_file,
159                                               score_str.c_str(),
160                                               score_len));
161   }
162
163   // If the oom_score_adj file doesn't exist, then we write the old
164   // style file and translate the oom_adj score to the range 0-15.
165   oom_file = oom_path.AppendASCII("oom_adj");
166   if (PathExists(oom_file)) {
167     // Max score for the old oom_adj range.  Used for conversion of new
168     // values to old values.
169     const int kMaxOldOomScore = 15;
170
171     int converted_score = score * kMaxOldOomScore / kMaxOomScore;
172     std::string score_str = IntToString(converted_score);
173     DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
174     int score_len = static_cast<int>(score_str.length());
175     return (score_len == file_util::WriteFile(oom_file,
176                                               score_str.c_str(),
177                                               score_len));
178   }
179
180   return false;
181 }
182
183 }  // namespace base