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

Side by Side Diff: base/trace_event/process_memory_dump.cc

Issue 2006943003: [tracing] Sanitize process memory dumps for background mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@whitelist_mdp
Patch Set: Created 4 years, 7 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "base/trace_event/process_memory_dump.h" 5 #include "base/trace_event/process_memory_dump.h"
6 6
7 #include <ctype.h>
7 #include <errno.h> 8 #include <errno.h>
8 9
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
12 #include "base/process/process_metrics.h" 13 #include "base/process/process_metrics.h"
13 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
14 #include "base/trace_event/heap_profiler_heap_dump_writer.h" 15 #include "base/trace_event/heap_profiler_heap_dump_writer.h"
16 #include "base/trace_event/memory_dump_request_args.h"
15 #include "base/trace_event/process_memory_totals.h" 17 #include "base/trace_event/process_memory_totals.h"
16 #include "base/trace_event/trace_event_argument.h" 18 #include "base/trace_event/trace_event_argument.h"
17 #include "build/build_config.h" 19 #include "build/build_config.h"
18 20
19 #if defined(OS_IOS) 21 #if defined(OS_IOS)
20 #include <sys/sysctl.h> 22 #include <sys/sysctl.h>
21 #endif 23 #endif
22 24
23 #if defined(OS_POSIX) 25 #if defined(OS_POSIX)
24 #include <sys/mman.h> 26 #include <sys/mman.h>
(...skipping 14 matching lines...) Expand all
39 const MemoryAllocatorDumpGuid& guid) { 41 const MemoryAllocatorDumpGuid& guid) {
40 return "global/" + guid.ToString(); 42 return "global/" + guid.ToString();
41 } 43 }
42 44
43 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) 45 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
44 size_t GetSystemPageCount(size_t mapped_size, size_t page_size) { 46 size_t GetSystemPageCount(size_t mapped_size, size_t page_size) {
45 return (mapped_size + page_size - 1) / page_size; 47 return (mapped_size + page_size - 1) / page_size;
46 } 48 }
47 #endif 49 #endif
48 50
51 // A list of string names that are allowed for the allocator dumps in background
52 // mode.
53 const char* const kDumpNameWhitelist[] = {
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 Ok I think at this point we want a memory_infra_ba
ssid 2016/05/31 22:33:20 Done.
54 // TODO(ssid): Fill this list with dump names, crbug.com/613198.
55 "",
56 };
57
58 // Check if the string is in the whitelist.
59 bool IsNameValidForBackgroundMode(const std::string& name,
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 s/Valid/Whitelisted/ ... which makes then the comm
ssid 2016/05/31 22:33:20 Acknowledged.
60 const char* whitelisted_name_for_testing) {
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 see my comment in the other cl, having to pass thi
ssid 2016/05/31 22:33:20 Done.
61 static size_t kListSize = arraysize(kDumpNameWhitelist);
62
63 // Remove special characters, numbers (including hexadecimal which are makred
Dmitry Skiba 2016/05/31 06:48:46 *marked
ssid 2016/05/31 22:33:20 Done.
64 // by '0x') from the given string.
65 const size_t length = name.size();
66 std::unique_ptr<char[]> stripped_str(new char[length]);
Dmitry Skiba 2016/05/31 06:48:46 Uhm, why not std::string? And push_back() instead
ssid 2016/05/31 22:33:20 Done.
67 size_t str_index = 0;
68 bool parsing_hex = false;
69 for (size_t i = 0; i < length; ++i) {
70 if (parsing_hex) {
71 if (isxdigit(name[i])) {
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 instead of having this state machine here, can you
ssid 2016/05/27 17:42:48 Sorry, I don't get it. Yeah I would still need thi
Primiano Tucci (use gerrit) 2016/05/27 17:51:19 Ok sorry this was a stupid comment from my side. I
ssid 2016/05/31 22:33:20 isalpha is there because there could be cases wher
Primiano Tucci (use gerrit) 2016/06/02 20:24:04 Ah right, I think it's ok.
72 continue;
73 } else {
74 parsing_hex = false;
75 }
76 }
77 if (i + 1 < length && name[i] == '0' && name[i + 1] == 'x') {
78 parsing_hex = true;
79 ++i;
80 } else if (isalpha(name[i])) {
81 stripped_str[str_index++] = name[i];
82 }
83 }
84 stripped_str[str_index] = '\0';
85
86 if (whitelisted_name_for_testing)
87 return strcmp(stripped_str.get(), whitelisted_name_for_testing) == 0;
88
89 for (size_t i = 0; i < kListSize; ++i) {
90 if (strcmp(stripped_str.get(), kDumpNameWhitelist[i]) == 0)
91 return true;
92 }
93 return false;
94 }
95
49 } // namespace 96 } // namespace
50 97
51 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) 98 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
52 // static 99 // static
53 size_t ProcessMemoryDump::GetSystemPageSize() { 100 size_t ProcessMemoryDump::GetSystemPageSize() {
54 #if defined(OS_IOS) 101 #if defined(OS_IOS)
55 // On iOS, getpagesize() returns the user page sizes, but for allocating 102 // On iOS, getpagesize() returns the user page sizes, but for allocating
56 // arrays for mincore(), kernel page sizes is needed. sysctlbyname() should 103 // arrays for mincore(), kernel page sizes is needed. sysctlbyname() should
57 // be used for this. Refer to crbug.com/542671 and Apple rdar://23651782 104 // be used for this. Refer to crbug.com/542671 and Apple rdar://23651782
58 int pagesize; 105 int pagesize;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 DCHECK(!failure); 188 DCHECK(!failure);
142 if (failure) { 189 if (failure) {
143 total_resident_size = 0; 190 total_resident_size = 0;
144 LOG(ERROR) << "CountResidentBytes failed. The resident size is invalid"; 191 LOG(ERROR) << "CountResidentBytes failed. The resident size is invalid";
145 } 192 }
146 return total_resident_size; 193 return total_resident_size;
147 } 194 }
148 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) 195 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED)
149 196
150 ProcessMemoryDump::ProcessMemoryDump( 197 ProcessMemoryDump::ProcessMemoryDump(
151 scoped_refptr<MemoryDumpSessionState> session_state) 198 scoped_refptr<MemoryDumpSessionState> session_state,
199 MemoryDumpLevelOfDetail level_of_detail)
152 : has_process_totals_(false), 200 : has_process_totals_(false),
153 has_process_mmaps_(false), 201 has_process_mmaps_(false),
154 session_state_(std::move(session_state)) {} 202 session_state_(std::move(session_state)),
203 level_of_detail_(level_of_detail),
204 whitelisted_name_for_testing_(nullptr) {
205 if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND) {
206 dummy_mad_.reset(new MemoryAllocatorDump("dummy", this));
207 }
208 }
155 209
156 ProcessMemoryDump::~ProcessMemoryDump() {} 210 ProcessMemoryDump::~ProcessMemoryDump() {}
157 211
158 MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( 212 MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
159 const std::string& absolute_name) { 213 const std::string& absolute_name) {
160 return AddAllocatorDumpInternal( 214 return AddAllocatorDumpInternal(
161 WrapUnique(new MemoryAllocatorDump(absolute_name, this))); 215 WrapUnique(new MemoryAllocatorDump(absolute_name, this)));
162 } 216 }
163 217
164 MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( 218 MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
165 const std::string& absolute_name, 219 const std::string& absolute_name,
166 const MemoryAllocatorDumpGuid& guid) { 220 const MemoryAllocatorDumpGuid& guid) {
167 return AddAllocatorDumpInternal( 221 return AddAllocatorDumpInternal(
168 WrapUnique(new MemoryAllocatorDump(absolute_name, this, guid))); 222 WrapUnique(new MemoryAllocatorDump(absolute_name, this, guid)));
169 } 223 }
170 224
171 MemoryAllocatorDump* ProcessMemoryDump::AddAllocatorDumpInternal( 225 MemoryAllocatorDump* ProcessMemoryDump::AddAllocatorDumpInternal(
172 std::unique_ptr<MemoryAllocatorDump> mad) { 226 std::unique_ptr<MemoryAllocatorDump> mad) {
227 // In background mode return dummy dump if invalid dump name is given.
228 if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND &&
229 !IsNameValidForBackgroundMode(mad->absolute_name(),
230 whitelisted_name_for_testing_)) {
231 return dummy_mad_.get();
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 maybe NOTREACHED also here to help debugging?
ssid 2016/05/31 22:33:20 I have changed the tests to use AddAllocatorDumpIn
Primiano Tucci (use gerrit) 2016/06/02 20:24:03 You can just check the allocator_dumps().count("na
232 }
233
173 auto insertion_result = allocator_dumps_.insert( 234 auto insertion_result = allocator_dumps_.insert(
174 std::make_pair(mad->absolute_name(), std::move(mad))); 235 std::make_pair(mad->absolute_name(), std::move(mad)));
175 MemoryAllocatorDump* inserted_mad = insertion_result.first->second.get(); 236 MemoryAllocatorDump* inserted_mad = insertion_result.first->second.get();
176 DCHECK(insertion_result.second) << "Duplicate name: " 237 DCHECK(insertion_result.second) << "Duplicate name: "
177 << inserted_mad->absolute_name(); 238 << inserted_mad->absolute_name();
178 return inserted_mad; 239 return inserted_mad;
179 } 240 }
180 241
181 MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump( 242 MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump(
182 const std::string& absolute_name) const { 243 const std::string& absolute_name) const {
183 auto it = allocator_dumps_.find(absolute_name); 244 auto it = allocator_dumps_.find(absolute_name);
184 return it == allocator_dumps_.end() ? nullptr : it->second.get(); 245 if (it != allocator_dumps_.end())
246 return it->second.get();
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 should you just leave this as it is and return nul
ssid 2016/05/27 17:42:48 I can't do that. Some dump providers assume that t
Primiano Tucci (use gerrit) 2016/06/02 20:24:03 Acknowledged.
247 return level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND
248 ? dummy_mad_.get()
249 : nullptr;
185 } 250 }
186 251
187 MemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump( 252 MemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump(
188 const std::string& absolute_name) { 253 const std::string& absolute_name) {
189 MemoryAllocatorDump* mad = GetAllocatorDump(absolute_name); 254 MemoryAllocatorDump* mad = GetAllocatorDump(absolute_name);
190 return mad ? mad : CreateAllocatorDump(absolute_name); 255 return mad ? mad : CreateAllocatorDump(absolute_name);
191 } 256 }
192 257
193 MemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump( 258 MemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump(
194 const MemoryAllocatorDumpGuid& guid) { 259 const MemoryAllocatorDumpGuid& guid) {
260 // Global dumps are disabled in background mode.
261 if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND)
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 I don't think global dumps are a problem right? th
ssid 2016/05/27 17:42:48 Global dumps are not required. Anyway we report ju
262 return dummy_mad_.get();
263
195 // A shared allocator dump can be shared within a process and the guid could 264 // A shared allocator dump can be shared within a process and the guid could
196 // have been created already. 265 // have been created already.
197 MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid); 266 MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
198 if (mad) { 267 if (mad) {
199 // The weak flag is cleared because this method should create a non-weak 268 // The weak flag is cleared because this method should create a non-weak
200 // dump. 269 // dump.
201 mad->clear_flags(MemoryAllocatorDump::Flags::WEAK); 270 mad->clear_flags(MemoryAllocatorDump::Flags::WEAK);
202 return mad; 271 return mad;
203 } 272 }
204 return CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid); 273 return CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid);
205 } 274 }
206 275
207 MemoryAllocatorDump* ProcessMemoryDump::CreateWeakSharedGlobalAllocatorDump( 276 MemoryAllocatorDump* ProcessMemoryDump::CreateWeakSharedGlobalAllocatorDump(
208 const MemoryAllocatorDumpGuid& guid) { 277 const MemoryAllocatorDumpGuid& guid) {
278 // Global dumps are disabled in background mode.
279 if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND)
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 ditto don't think you need this
280 return dummy_mad_.get();
281
209 MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid); 282 MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
210 if (mad) 283 if (mad)
211 return mad; 284 return mad;
212 mad = CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid); 285 mad = CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid);
213 mad->set_flags(MemoryAllocatorDump::Flags::WEAK); 286 mad->set_flags(MemoryAllocatorDump::Flags::WEAK);
214 return mad; 287 return mad;
215 } 288 }
216 289
217 MemoryAllocatorDump* ProcessMemoryDump::GetSharedGlobalAllocatorDump( 290 MemoryAllocatorDump* ProcessMemoryDump::GetSharedGlobalAllocatorDump(
218 const MemoryAllocatorDumpGuid& guid) const { 291 const MemoryAllocatorDumpGuid& guid) const {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 } 399 }
327 400
328 void ProcessMemoryDump::AddOwnershipEdge( 401 void ProcessMemoryDump::AddOwnershipEdge(
329 const MemoryAllocatorDumpGuid& source, 402 const MemoryAllocatorDumpGuid& source,
330 const MemoryAllocatorDumpGuid& target) { 403 const MemoryAllocatorDumpGuid& target) {
331 AddOwnershipEdge(source, target, 0 /* importance */); 404 AddOwnershipEdge(source, target, 0 /* importance */);
332 } 405 }
333 406
334 void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source, 407 void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source,
335 const std::string& target_node_name) { 408 const std::string& target_node_name) {
409 // Do not create new dumps for suballocations in background mode.
410 if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND)
Primiano Tucci (use gerrit) 2016/05/27 17:23:35 ditto
ssid 2016/05/27 17:42:48 Why create unnecessary dumps when we are not inter
411 return;
412
336 std::string child_mad_name = target_node_name + "/__" + source.ToString(); 413 std::string child_mad_name = target_node_name + "/__" + source.ToString();
337 MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name); 414 MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name);
338 AddOwnershipEdge(source, target_child_mad->guid()); 415 AddOwnershipEdge(source, target_child_mad->guid());
339 } 416 }
340 417
341 } // namespace trace_event 418 } // namespace trace_event
342 } // namespace base 419 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698