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

Side by Side Diff: util/win/process_info_test.cc

Issue 1370063005: MEM_RESERVE regions are not accessible by ReadProcessMemory() (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: . Created 5 years, 2 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
« no previous file with comments | « util/win/process_info.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/win/process_info.h" 15 #include "util/win/process_info.h"
16 16
17 #include <imagehlp.h> 17 #include <imagehlp.h>
18 #include <intrin.h> 18 #include <intrin.h>
19 #include <wchar.h> 19 #include <wchar.h>
20 20
21 #include "base/files/file_path.h" 21 #include "base/files/file_path.h"
22 #include "base/memory/scoped_ptr.h"
22 #include "build/build_config.h" 23 #include "build/build_config.h"
23 #include "gtest/gtest.h" 24 #include "gtest/gtest.h"
24 #include "test/paths.h" 25 #include "test/paths.h"
25 #include "test/win/child_launcher.h" 26 #include "test/win/child_launcher.h"
26 #include "util/file/file_io.h" 27 #include "util/file/file_io.h"
27 #include "util/misc/uuid.h" 28 #include "util/misc/uuid.h"
28 #include "util/win/scoped_handle.h" 29 #include "util/win/scoped_handle.h"
29 30
30 namespace crashpad { 31 namespace crashpad {
31 namespace test { 32 namespace test {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 222
222 mbi.BaseAddress = 0; 223 mbi.BaseAddress = 0;
223 mbi.RegionSize = 10; 224 mbi.RegionSize = 10;
224 mbi.State = MEM_COMMIT; 225 mbi.State = MEM_COMMIT;
225 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 226 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
226 227
227 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 228 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
228 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(2, 4), 229 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(2, 4),
229 memory_info); 230 memory_info);
230 231
231 ASSERT_EQ(result.size(), 1u); 232 ASSERT_EQ(1u, result.size());
232 EXPECT_EQ(2, result[0].base()); 233 EXPECT_EQ(2, result[0].base());
233 EXPECT_EQ(4, result[0].size()); 234 EXPECT_EQ(4, result[0].size());
234 } 235 }
235 236
236 TEST(ProcessInfo, AccessibleRangesOneTruncatedSize) { 237 TEST(ProcessInfo, AccessibleRangesOneTruncatedSize) {
237 std::vector<ProcessInfo::MemoryInfo> memory_info; 238 std::vector<ProcessInfo::MemoryInfo> memory_info;
238 MEMORY_BASIC_INFORMATION mbi = {0}; 239 MEMORY_BASIC_INFORMATION mbi = {0};
239 240
240 mbi.BaseAddress = 0; 241 mbi.BaseAddress = 0;
241 mbi.RegionSize = 10; 242 mbi.RegionSize = 10;
242 mbi.State = MEM_COMMIT; 243 mbi.State = MEM_COMMIT;
243 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 244 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
244 245
245 mbi.BaseAddress = reinterpret_cast<void*>(10); 246 mbi.BaseAddress = reinterpret_cast<void*>(10);
246 mbi.RegionSize = 20; 247 mbi.RegionSize = 20;
247 mbi.State = MEM_FREE; 248 mbi.State = MEM_FREE;
248 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 249 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
249 250
250 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 251 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
251 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), 252 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
252 memory_info); 253 memory_info);
253 254
254 ASSERT_EQ(result.size(), 1u); 255 ASSERT_EQ(1u, result.size());
255 EXPECT_EQ(5, result[0].base()); 256 EXPECT_EQ(5, result[0].base());
256 EXPECT_EQ(5, result[0].size()); 257 EXPECT_EQ(5, result[0].size());
257 } 258 }
258 259
259 TEST(ProcessInfo, AccessibleRangesOneMovedStart) { 260 TEST(ProcessInfo, AccessibleRangesOneMovedStart) {
260 std::vector<ProcessInfo::MemoryInfo> memory_info; 261 std::vector<ProcessInfo::MemoryInfo> memory_info;
261 MEMORY_BASIC_INFORMATION mbi = {0}; 262 MEMORY_BASIC_INFORMATION mbi = {0};
262 263
263 mbi.BaseAddress = 0; 264 mbi.BaseAddress = 0;
264 mbi.RegionSize = 10; 265 mbi.RegionSize = 10;
265 mbi.State = MEM_FREE; 266 mbi.State = MEM_FREE;
266 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 267 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
267 268
268 mbi.BaseAddress = reinterpret_cast<void*>(10); 269 mbi.BaseAddress = reinterpret_cast<void*>(10);
269 mbi.RegionSize = 20; 270 mbi.RegionSize = 20;
270 mbi.State = MEM_COMMIT; 271 mbi.State = MEM_COMMIT;
271 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 272 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
272 273
273 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 274 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
274 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), 275 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
275 memory_info); 276 memory_info);
276 277
277 ASSERT_EQ(result.size(), 1u); 278 ASSERT_EQ(1u, result.size());
278 EXPECT_EQ(10, result[0].base()); 279 EXPECT_EQ(10, result[0].base());
279 EXPECT_EQ(5, result[0].size()); 280 EXPECT_EQ(5, result[0].size());
280 } 281 }
282
283 TEST(ProcessInfo, ReserveIsInaccessible) {
284 std::vector<ProcessInfo::MemoryInfo> memory_info;
285 MEMORY_BASIC_INFORMATION mbi = {0};
286
287 mbi.BaseAddress = 0;
288 mbi.RegionSize = 10;
289 mbi.State = MEM_RESERVE;
290 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
291
292 mbi.BaseAddress = reinterpret_cast<void*>(10);
293 mbi.RegionSize = 20;
294 mbi.State = MEM_COMMIT;
295 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
296
297 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
298 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
299 memory_info);
300
301 ASSERT_EQ(1u, result.size());
302 EXPECT_EQ(10, result[0].base());
303 EXPECT_EQ(5, result[0].size());
304 }
305
306 TEST(ProcessInfo, PageGuardIsInaccessible) {
307 std::vector<ProcessInfo::MemoryInfo> memory_info;
308 MEMORY_BASIC_INFORMATION mbi = {0};
309
310 mbi.BaseAddress = 0;
311 mbi.RegionSize = 10;
312 mbi.State = MEM_COMMIT;
313 mbi.Protect = PAGE_GUARD;
314 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
315
316 mbi.BaseAddress = reinterpret_cast<void*>(10);
317 mbi.RegionSize = 20;
318 mbi.State = MEM_COMMIT;
319 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
320
321 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
322 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
323 memory_info);
324
325 ASSERT_EQ(1u, result.size());
326 EXPECT_EQ(10, result[0].base());
327 EXPECT_EQ(5, result[0].size());
328 }
329
330 TEST(ProcessInfo, PageNoAccessIsInaccessible) {
331 std::vector<ProcessInfo::MemoryInfo> memory_info;
332 MEMORY_BASIC_INFORMATION mbi = {0};
333
334 mbi.BaseAddress = 0;
335 mbi.RegionSize = 10;
336 mbi.State = MEM_COMMIT;
337 mbi.Protect = PAGE_NOACCESS;
338 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
339
340 mbi.BaseAddress = reinterpret_cast<void*>(10);
341 mbi.RegionSize = 20;
342 mbi.State = MEM_COMMIT;
343 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
344
345 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
346 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
347 memory_info);
348
349 ASSERT_EQ(1u, result.size());
350 EXPECT_EQ(10, result[0].base());
351 EXPECT_EQ(5, result[0].size());
352 }
281 353
282 TEST(ProcessInfo, AccessibleRangesCoalesced) { 354 TEST(ProcessInfo, AccessibleRangesCoalesced) {
283 std::vector<ProcessInfo::MemoryInfo> memory_info; 355 std::vector<ProcessInfo::MemoryInfo> memory_info;
284 MEMORY_BASIC_INFORMATION mbi = {0}; 356 MEMORY_BASIC_INFORMATION mbi = {0};
285 357
286 mbi.BaseAddress = 0; 358 mbi.BaseAddress = 0;
287 mbi.RegionSize = 10; 359 mbi.RegionSize = 10;
288 mbi.State = MEM_FREE; 360 mbi.State = MEM_FREE;
289 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 361 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
290 362
291 mbi.BaseAddress = reinterpret_cast<void*>(10); 363 mbi.BaseAddress = reinterpret_cast<void*>(10);
292 mbi.RegionSize = 2; 364 mbi.RegionSize = 2;
293 mbi.State = MEM_COMMIT; 365 mbi.State = MEM_COMMIT;
294 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 366 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
295 367
296 mbi.BaseAddress = reinterpret_cast<void*>(12); 368 mbi.BaseAddress = reinterpret_cast<void*>(12);
297 mbi.RegionSize = 5; 369 mbi.RegionSize = 5;
298 mbi.State = MEM_RESERVE; 370 mbi.State = MEM_COMMIT;
299 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 371 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
300 372
301 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 373 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
302 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4), 374 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4),
303 memory_info); 375 memory_info);
304 376
305 ASSERT_EQ(result.size(), 1u); 377 ASSERT_EQ(1u, result.size());
306 EXPECT_EQ(11, result[0].base()); 378 EXPECT_EQ(11, result[0].base());
307 EXPECT_EQ(4, result[0].size()); 379 EXPECT_EQ(4, result[0].size());
308 } 380 }
309 381
310 TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) { 382 TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) {
311 std::vector<ProcessInfo::MemoryInfo> memory_info; 383 std::vector<ProcessInfo::MemoryInfo> memory_info;
312 MEMORY_BASIC_INFORMATION mbi = {0}; 384 MEMORY_BASIC_INFORMATION mbi = {0};
313 385
314 mbi.BaseAddress = 0; 386 mbi.BaseAddress = 0;
315 mbi.RegionSize = 10; 387 mbi.RegionSize = 10;
316 mbi.State = MEM_COMMIT; 388 mbi.State = MEM_COMMIT;
317 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 389 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
318 390
319 mbi.BaseAddress = reinterpret_cast<void*>(10); 391 mbi.BaseAddress = reinterpret_cast<void*>(10);
320 mbi.RegionSize = 5; 392 mbi.RegionSize = 5;
321 mbi.State = MEM_FREE; 393 mbi.State = MEM_FREE;
322 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 394 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
323 395
324 mbi.BaseAddress = reinterpret_cast<void*>(15); 396 mbi.BaseAddress = reinterpret_cast<void*>(15);
325 mbi.RegionSize = 100; 397 mbi.RegionSize = 100;
326 mbi.State = MEM_COMMIT; 398 mbi.State = MEM_COMMIT;
327 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 399 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
328 400
329 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 401 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
330 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45), 402 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45),
331 memory_info); 403 memory_info);
332 404
333 ASSERT_EQ(result.size(), 2u); 405 ASSERT_EQ(2u, result.size());
334 EXPECT_EQ(5, result[0].base()); 406 EXPECT_EQ(5, result[0].base());
335 EXPECT_EQ(5, result[0].size()); 407 EXPECT_EQ(5, result[0].size());
336 EXPECT_EQ(15, result[1].base()); 408 EXPECT_EQ(15, result[1].base());
337 EXPECT_EQ(35, result[1].size()); 409 EXPECT_EQ(35, result[1].size());
338 } 410 }
339 411
340 TEST(ProcessInfo, RequestedBeforeMap) { 412 TEST(ProcessInfo, RequestedBeforeMap) {
341 std::vector<ProcessInfo::MemoryInfo> memory_info; 413 std::vector<ProcessInfo::MemoryInfo> memory_info;
342 MEMORY_BASIC_INFORMATION mbi = {0}; 414 MEMORY_BASIC_INFORMATION mbi = {0};
343 415
344 mbi.BaseAddress = reinterpret_cast<void*>(10); 416 mbi.BaseAddress = reinterpret_cast<void*>(10);
345 mbi.RegionSize = 10; 417 mbi.RegionSize = 10;
346 mbi.State = MEM_COMMIT; 418 mbi.State = MEM_COMMIT;
347 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 419 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
348 420
349 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 421 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
350 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), 422 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
351 memory_info); 423 memory_info);
352 424
353 ASSERT_EQ(result.size(), 1u); 425 ASSERT_EQ(1u, result.size());
354 EXPECT_EQ(10, result[0].base()); 426 EXPECT_EQ(10, result[0].base());
355 EXPECT_EQ(5, result[0].size()); 427 EXPECT_EQ(5, result[0].size());
356 } 428 }
357 429
358 TEST(ProcessInfo, RequestedAfterMap) { 430 TEST(ProcessInfo, RequestedAfterMap) {
359 std::vector<ProcessInfo::MemoryInfo> memory_info; 431 std::vector<ProcessInfo::MemoryInfo> memory_info;
360 MEMORY_BASIC_INFORMATION mbi = {0}; 432 MEMORY_BASIC_INFORMATION mbi = {0};
361 433
362 mbi.BaseAddress = reinterpret_cast<void*>(10); 434 mbi.BaseAddress = reinterpret_cast<void*>(10);
363 mbi.RegionSize = 10; 435 mbi.RegionSize = 10;
364 mbi.State = MEM_COMMIT; 436 mbi.State = MEM_COMMIT;
365 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 437 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
366 438
367 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 439 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
368 GetReadableRangesOfMemoryMap( 440 GetReadableRangesOfMemoryMap(
369 CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info); 441 CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info);
370 442
371 ASSERT_EQ(result.size(), 1u); 443 ASSERT_EQ(1u, result.size());
372 EXPECT_EQ(15, result[0].base()); 444 EXPECT_EQ(15, result[0].base());
373 EXPECT_EQ(5, result[0].size()); 445 EXPECT_EQ(5, result[0].size());
374 } 446 }
375 447
448 TEST(ProcessInfo, ReadableRanges) {
449 SYSTEM_INFO system_info;
450 GetSystemInfo(&system_info);
451
452 const size_t kBlockSize = system_info.dwPageSize;
453
454 // Allocate 6 pages, and then commit the second, fourth, and fifth, and mark
455 // two as committed, but PAGE_NOACCESS, so we have a setup like this:
456 // 0 1 2 3 4 5
457 // +-----------------------------------------------+
458 // | ????? | | xxxxx | | | ????? |
459 // +-----------------------------------------------+
460 void* reserve_region =
461 VirtualAlloc(nullptr, kBlockSize * 6, MEM_RESERVE, PAGE_READWRITE);
462 ASSERT_TRUE(reserve_region);
463 uintptr_t reserved_as_int = reinterpret_cast<uintptr_t>(reserve_region);
464 void* readable1 =
465 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + kBlockSize),
466 kBlockSize,
467 MEM_COMMIT,
468 PAGE_READWRITE);
469 ASSERT_TRUE(readable1);
470 void* readable2 =
471 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 3)),
472 kBlockSize * 2,
473 MEM_COMMIT,
474 PAGE_READWRITE);
475 ASSERT_TRUE(readable2);
476
477 void* no_access =
478 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 2)),
479 kBlockSize,
480 MEM_COMMIT,
481 PAGE_NOACCESS);
482 ASSERT_TRUE(no_access);
483
484 HANDLE current_process = GetCurrentProcess();
485 ProcessInfo info;
486 info.Initialize(current_process);
487 auto ranges = info.GetReadableRanges(
488 CheckedRange<WinVMAddress, WinVMSize>(reserved_as_int, kBlockSize * 6));
489
490 ASSERT_EQ(2u, ranges.size());
491 EXPECT_EQ(reserved_as_int + kBlockSize, ranges[0].base());
492 EXPECT_EQ(kBlockSize, ranges[0].size());
493 EXPECT_EQ(reserved_as_int + (kBlockSize * 3), ranges[1].base());
494 EXPECT_EQ(kBlockSize * 2, ranges[1].size());
495
496 // Also make sure what we think we can read corresponds with what we can
497 // actually read.
498 scoped_ptr<unsigned char[]> into(new unsigned char[kBlockSize * 6]);
499 SIZE_T bytes_read;
500
501 EXPECT_TRUE(ReadProcessMemory(
502 current_process, readable1, into.get(), kBlockSize, &bytes_read));
503 EXPECT_EQ(kBlockSize, bytes_read);
504
505 EXPECT_TRUE(ReadProcessMemory(
506 current_process, readable2, into.get(), kBlockSize * 2, &bytes_read));
507 EXPECT_EQ(kBlockSize * 2, bytes_read);
508
509 EXPECT_FALSE(ReadProcessMemory(
510 current_process,
511 reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 2)),
Mark Mentovai 2015/10/01 22:22:29 Can this be no_access instead of this monstrosity?
scottmg 2015/10/01 22:28:10 Darn, not quite "unqualified". Done.
512 into.get(),
513 kBlockSize,
514 &bytes_read));
515 EXPECT_FALSE(ReadProcessMemory(
516 current_process, reserve_region, into.get(), kBlockSize, &bytes_read));
517 EXPECT_FALSE(ReadProcessMemory(current_process,
518 reserve_region,
519 into.get(),
520 kBlockSize * 6,
521 &bytes_read));
522 }
523
376 } // namespace 524 } // namespace
377 } // namespace test 525 } // namespace test
378 } // namespace crashpad 526 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/win/process_info.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698