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

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 mbi.Protect = 0;
320 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
321
322 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
323 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
324 memory_info);
325
326 ASSERT_EQ(1u, result.size());
327 EXPECT_EQ(10, result[0].base());
328 EXPECT_EQ(5, result[0].size());
329 }
330
331 TEST(ProcessInfo, PageNoAccessIsInaccessible) {
332 std::vector<ProcessInfo::MemoryInfo> memory_info;
333 MEMORY_BASIC_INFORMATION mbi = {0};
334
335 mbi.BaseAddress = 0;
336 mbi.RegionSize = 10;
337 mbi.State = MEM_COMMIT;
338 mbi.Protect = PAGE_NOACCESS;
339 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
340
341 mbi.BaseAddress = reinterpret_cast<void*>(10);
342 mbi.RegionSize = 20;
343 mbi.State = MEM_COMMIT;
344 mbi.Protect = 0;
345 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
346
347 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
348 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
349 memory_info);
350
351 ASSERT_EQ(1u, result.size());
352 EXPECT_EQ(10, result[0].base());
353 EXPECT_EQ(5, result[0].size());
354 }
281 355
282 TEST(ProcessInfo, AccessibleRangesCoalesced) { 356 TEST(ProcessInfo, AccessibleRangesCoalesced) {
283 std::vector<ProcessInfo::MemoryInfo> memory_info; 357 std::vector<ProcessInfo::MemoryInfo> memory_info;
284 MEMORY_BASIC_INFORMATION mbi = {0}; 358 MEMORY_BASIC_INFORMATION mbi = {0};
285 359
286 mbi.BaseAddress = 0; 360 mbi.BaseAddress = 0;
287 mbi.RegionSize = 10; 361 mbi.RegionSize = 10;
288 mbi.State = MEM_FREE; 362 mbi.State = MEM_FREE;
289 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 363 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
290 364
291 mbi.BaseAddress = reinterpret_cast<void*>(10); 365 mbi.BaseAddress = reinterpret_cast<void*>(10);
292 mbi.RegionSize = 2; 366 mbi.RegionSize = 2;
293 mbi.State = MEM_COMMIT; 367 mbi.State = MEM_COMMIT;
294 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 368 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
295 369
296 mbi.BaseAddress = reinterpret_cast<void*>(12); 370 mbi.BaseAddress = reinterpret_cast<void*>(12);
297 mbi.RegionSize = 5; 371 mbi.RegionSize = 5;
298 mbi.State = MEM_RESERVE; 372 mbi.State = MEM_COMMIT;
299 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 373 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
300 374
301 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 375 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
302 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4), 376 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4),
303 memory_info); 377 memory_info);
304 378
305 ASSERT_EQ(result.size(), 1u); 379 ASSERT_EQ(1u, result.size());
306 EXPECT_EQ(11, result[0].base()); 380 EXPECT_EQ(11, result[0].base());
307 EXPECT_EQ(4, result[0].size()); 381 EXPECT_EQ(4, result[0].size());
308 } 382 }
309 383
310 TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) { 384 TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) {
311 std::vector<ProcessInfo::MemoryInfo> memory_info; 385 std::vector<ProcessInfo::MemoryInfo> memory_info;
312 MEMORY_BASIC_INFORMATION mbi = {0}; 386 MEMORY_BASIC_INFORMATION mbi = {0};
313 387
314 mbi.BaseAddress = 0; 388 mbi.BaseAddress = 0;
315 mbi.RegionSize = 10; 389 mbi.RegionSize = 10;
316 mbi.State = MEM_COMMIT; 390 mbi.State = MEM_COMMIT;
317 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 391 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
318 392
319 mbi.BaseAddress = reinterpret_cast<void*>(10); 393 mbi.BaseAddress = reinterpret_cast<void*>(10);
320 mbi.RegionSize = 5; 394 mbi.RegionSize = 5;
321 mbi.State = MEM_FREE; 395 mbi.State = MEM_FREE;
322 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 396 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
323 397
324 mbi.BaseAddress = reinterpret_cast<void*>(15); 398 mbi.BaseAddress = reinterpret_cast<void*>(15);
325 mbi.RegionSize = 100; 399 mbi.RegionSize = 100;
326 mbi.State = MEM_COMMIT; 400 mbi.State = MEM_COMMIT;
327 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 401 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
328 402
329 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 403 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
330 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45), 404 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45),
331 memory_info); 405 memory_info);
332 406
333 ASSERT_EQ(result.size(), 2u); 407 ASSERT_EQ(2u, result.size());
334 EXPECT_EQ(5, result[0].base()); 408 EXPECT_EQ(5, result[0].base());
335 EXPECT_EQ(5, result[0].size()); 409 EXPECT_EQ(5, result[0].size());
336 EXPECT_EQ(15, result[1].base()); 410 EXPECT_EQ(15, result[1].base());
337 EXPECT_EQ(35, result[1].size()); 411 EXPECT_EQ(35, result[1].size());
338 } 412 }
339 413
340 TEST(ProcessInfo, RequestedBeforeMap) { 414 TEST(ProcessInfo, RequestedBeforeMap) {
341 std::vector<ProcessInfo::MemoryInfo> memory_info; 415 std::vector<ProcessInfo::MemoryInfo> memory_info;
342 MEMORY_BASIC_INFORMATION mbi = {0}; 416 MEMORY_BASIC_INFORMATION mbi = {0};
343 417
344 mbi.BaseAddress = reinterpret_cast<void*>(10); 418 mbi.BaseAddress = reinterpret_cast<void*>(10);
345 mbi.RegionSize = 10; 419 mbi.RegionSize = 10;
346 mbi.State = MEM_COMMIT; 420 mbi.State = MEM_COMMIT;
347 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 421 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
348 422
349 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 423 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
350 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), 424 GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10),
351 memory_info); 425 memory_info);
352 426
353 ASSERT_EQ(result.size(), 1u); 427 ASSERT_EQ(1u, result.size());
354 EXPECT_EQ(10, result[0].base()); 428 EXPECT_EQ(10, result[0].base());
355 EXPECT_EQ(5, result[0].size()); 429 EXPECT_EQ(5, result[0].size());
356 } 430 }
357 431
358 TEST(ProcessInfo, RequestedAfterMap) { 432 TEST(ProcessInfo, RequestedAfterMap) {
359 std::vector<ProcessInfo::MemoryInfo> memory_info; 433 std::vector<ProcessInfo::MemoryInfo> memory_info;
360 MEMORY_BASIC_INFORMATION mbi = {0}; 434 MEMORY_BASIC_INFORMATION mbi = {0};
361 435
362 mbi.BaseAddress = reinterpret_cast<void*>(10); 436 mbi.BaseAddress = reinterpret_cast<void*>(10);
363 mbi.RegionSize = 10; 437 mbi.RegionSize = 10;
364 mbi.State = MEM_COMMIT; 438 mbi.State = MEM_COMMIT;
365 memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); 439 memory_info.push_back(ProcessInfo::MemoryInfo(mbi));
366 440
367 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = 441 std::vector<CheckedRange<WinVMAddress, WinVMSize>> result =
368 GetReadableRangesOfMemoryMap( 442 GetReadableRangesOfMemoryMap(
369 CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info); 443 CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info);
370 444
371 ASSERT_EQ(result.size(), 1u); 445 ASSERT_EQ(1u, result.size());
372 EXPECT_EQ(15, result[0].base()); 446 EXPECT_EQ(15, result[0].base());
373 EXPECT_EQ(5, result[0].size()); 447 EXPECT_EQ(5, result[0].size());
374 } 448 }
375 449
450 TEST(ProcessInfo, ReadableRanges) {
451 SYSTEM_INFO system_info;
452 GetSystemInfo(&system_info);
453
454 const size_t kBlockSize = system_info.dwPageSize;
455
456 // Allocate 6 pages, and then commit the second, fourth, and fifth, and mark
457 // two as committed, but PAGE_NOACCESS, so we have a setup like this:
458 // 0 1 2 3 4 5
459 // +-----------------------------------------------+
460 // | ????? | | xxxxx | | | ????? |
461 // +-----------------------------------------------+
462 void* reserve_region =
463 VirtualAlloc(nullptr, kBlockSize * 6, MEM_RESERVE, PAGE_READWRITE);
464 ASSERT_TRUE(reserve_region);
465 uintptr_t reserved_as_int = reinterpret_cast<uintptr_t>(reserve_region);
466 void* readable1 =
467 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + kBlockSize),
468 kBlockSize,
469 MEM_COMMIT,
470 PAGE_READWRITE);
471 ASSERT_TRUE(readable1);
472 void* readable2 =
473 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 3)),
474 kBlockSize * 2,
475 MEM_COMMIT,
476 PAGE_READWRITE);
477 ASSERT_TRUE(readable2);
478
479 void* no_access =
480 VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 2)),
481 kBlockSize,
482 MEM_COMMIT,
483 PAGE_NOACCESS);
484 ASSERT_TRUE(no_access);
485
486 HANDLE current_process = GetCurrentProcess();
487 ProcessInfo info;
488 info.Initialize(current_process);
489 auto ranges = info.GetReadableRanges(
490 CheckedRange<WinVMAddress, WinVMSize>(reserved_as_int, kBlockSize * 6));
491
492 ASSERT_EQ(2u, ranges.size());
493 EXPECT_EQ(reserved_as_int + kBlockSize, ranges[0].base());
494 EXPECT_EQ(kBlockSize, ranges[0].size());
495 EXPECT_EQ(reserved_as_int + (kBlockSize * 3), ranges[1].base());
496 EXPECT_EQ(kBlockSize * 2, ranges[1].size());
497
498 // Also make sure what we think we can read corresponds with what we can
499 // actually read.
500 scoped_ptr<unsigned char[]> into(new unsigned char[kBlockSize * 6]);
501 SIZE_T bytes_read;
502
503 EXPECT_TRUE(ReadProcessMemory(
504 current_process, readable1, into.get(), kBlockSize, &bytes_read));
505 EXPECT_EQ(kBlockSize, bytes_read);
506
507 EXPECT_TRUE(ReadProcessMemory(
508 current_process, readable2, into.get(), kBlockSize * 2, &bytes_read));
509 EXPECT_EQ(kBlockSize * 2, bytes_read);
510
511 EXPECT_FALSE(ReadProcessMemory(
512 current_process, no_access, into.get(), kBlockSize, &bytes_read));
513 EXPECT_FALSE(ReadProcessMemory(
514 current_process, reserve_region, into.get(), kBlockSize, &bytes_read));
515 EXPECT_FALSE(ReadProcessMemory(current_process,
516 reserve_region,
517 into.get(),
518 kBlockSize * 6,
519 &bytes_read));
520 }
521
376 } // namespace 522 } // namespace
377 } // namespace test 523 } // namespace test
378 } // namespace crashpad 524 } // 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