1 // Copyright (c) 2012 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/memory/shared_memory.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include <memory> 11 12 #include "base/atomicops.h" 13 #include "base/macros.h" 14 #include "base/memory/shared_memory_handle.h" 15 #include "base/process/kill.h" 16 #include "base/rand_util.h" 17 #include "base/strings/string_number_conversions.h" 18 #include "base/sys_info.h" 19 #include "base/test/multiprocess_test.h" 20 #include "base/threading/platform_thread.h" 21 #include "base/time/time.h" 22 #include "build/build_config.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/multiprocess_func_list.h" 25 26 #if defined(OS_POSIX) 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <sys/mman.h> 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 #include <unistd.h> 33 #endif 34 35 #if defined(OS_WIN) 36 #include "base/win/scoped_handle.h" 37 #endif 38 39 namespace base { 40 41 namespace { 42 43 #if !defined(OS_MACOSX) 44 // Each thread will open the shared memory. Each thread will take a different 4 45 // byte int pointer, and keep changing it, with some small pauses in between. 46 // Verify that each thread's value in the shared memory is always correct. 47 class MultipleThreadMain : public PlatformThread::Delegate { 48 public: 49 explicit MultipleThreadMain(int16_t id) : id_(id) {} 50 ~MultipleThreadMain() override {} 51 52 static void CleanUp() { 53 SharedMemory memory; 54 memory.Delete(s_test_name_); 55 } 56 57 // PlatformThread::Delegate interface. 58 void ThreadMain() override { 59 const uint32_t kDataSize = 1024; 60 SharedMemory memory; 61 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); 62 EXPECT_TRUE(rv); 63 rv = memory.Map(kDataSize); 64 EXPECT_TRUE(rv); 65 int* ptr = static_cast<int*>(memory.memory()) + id_; 66 EXPECT_EQ(0, *ptr); 67 68 for (int idx = 0; idx < 100; idx++) { 69 *ptr = idx; 70 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 71 EXPECT_EQ(*ptr, idx); 72 } 73 // Reset back to 0 for the next test that uses the same name. 74 *ptr = 0; 75 76 memory.Close(); 77 } 78 79 private: 80 int16_t id_; 81 82 static const char s_test_name_[]; 83 84 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); 85 }; 86 87 const char MultipleThreadMain::s_test_name_[] = 88 "SharedMemoryOpenThreadTest"; 89 #endif // !defined(OS_MACOSX) 90 91 } // namespace 92 93 // Android/Mac doesn't support SharedMemory::Open/Delete/ 94 // CreateNamedDeprecated(openExisting=true) 95 #if !defined(OS_ANDROID) && !defined(OS_MACOSX) 96 TEST(SharedMemoryTest, OpenClose) { 97 const uint32_t kDataSize = 1024; 98 std::string test_name = "SharedMemoryOpenCloseTest"; 99 100 // Open two handles to a memory segment, confirm that they are mapped 101 // separately yet point to the same space. 102 SharedMemory memory1; 103 bool rv = memory1.Delete(test_name); 104 EXPECT_TRUE(rv); 105 rv = memory1.Delete(test_name); 106 EXPECT_TRUE(rv); 107 rv = memory1.Open(test_name, false); 108 EXPECT_FALSE(rv); 109 rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 110 EXPECT_TRUE(rv); 111 rv = memory1.Map(kDataSize); 112 EXPECT_TRUE(rv); 113 SharedMemory memory2; 114 rv = memory2.Open(test_name, false); 115 EXPECT_TRUE(rv); 116 rv = memory2.Map(kDataSize); 117 EXPECT_TRUE(rv); 118 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. 119 120 // Make sure we don't segfault. (it actually happened!) 121 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); 122 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); 123 124 // Write data to the first memory segment, verify contents of second. 125 memset(memory1.memory(), '1', kDataSize); 126 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); 127 128 // Close the first memory segment, and verify the second has the right data. 129 memory1.Close(); 130 char* start_ptr = static_cast<char*>(memory2.memory()); 131 char* end_ptr = start_ptr + kDataSize; 132 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) 133 EXPECT_EQ(*ptr, '1'); 134 135 // Close the second memory segment. 136 memory2.Close(); 137 138 rv = memory1.Delete(test_name); 139 EXPECT_TRUE(rv); 140 rv = memory2.Delete(test_name); 141 EXPECT_TRUE(rv); 142 } 143 144 TEST(SharedMemoryTest, OpenExclusive) { 145 const uint32_t kDataSize = 1024; 146 const uint32_t kDataSize2 = 2048; 147 std::ostringstream test_name_stream; 148 test_name_stream << "SharedMemoryOpenExclusiveTest." 149 << Time::Now().ToDoubleT(); 150 std::string test_name = test_name_stream.str(); 151 152 // Open two handles to a memory segment and check that 153 // open_existing_deprecated works as expected. 154 SharedMemory memory1; 155 bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 156 EXPECT_TRUE(rv); 157 158 // Memory1 knows it's size because it created it. 159 EXPECT_EQ(memory1.requested_size(), kDataSize); 160 161 rv = memory1.Map(kDataSize); 162 EXPECT_TRUE(rv); 163 164 // The mapped memory1 must be at least the size we asked for. 165 EXPECT_GE(memory1.mapped_size(), kDataSize); 166 167 // The mapped memory1 shouldn't exceed rounding for allocation granularity. 168 EXPECT_LT(memory1.mapped_size(), 169 kDataSize + SysInfo::VMAllocationGranularity()); 170 171 memset(memory1.memory(), 'G', kDataSize); 172 173 SharedMemory memory2; 174 // Should not be able to create if openExisting is false. 175 rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); 176 EXPECT_FALSE(rv); 177 178 // Should be able to create with openExisting true. 179 rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); 180 EXPECT_TRUE(rv); 181 182 // Memory2 shouldn't know the size because we didn't create it. 183 EXPECT_EQ(memory2.requested_size(), 0U); 184 185 // We should be able to map the original size. 186 rv = memory2.Map(kDataSize); 187 EXPECT_TRUE(rv); 188 189 // The mapped memory2 must be at least the size of the original. 190 EXPECT_GE(memory2.mapped_size(), kDataSize); 191 192 // The mapped memory2 shouldn't exceed rounding for allocation granularity. 193 EXPECT_LT(memory2.mapped_size(), 194 kDataSize2 + SysInfo::VMAllocationGranularity()); 195 196 // Verify that opening memory2 didn't truncate or delete memory 1. 197 char* start_ptr = static_cast<char*>(memory2.memory()); 198 char* end_ptr = start_ptr + kDataSize; 199 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { 200 EXPECT_EQ(*ptr, 'G'); 201 } 202 203 memory1.Close(); 204 memory2.Close(); 205 206 rv = memory1.Delete(test_name); 207 EXPECT_TRUE(rv); 208 } 209 #endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) 210 211 // Check that memory is still mapped after its closed. 212 TEST(SharedMemoryTest, CloseNoUnmap) { 213 const size_t kDataSize = 4096; 214 215 SharedMemory memory; 216 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 217 char* ptr = static_cast<char*>(memory.memory()); 218 ASSERT_NE(ptr, static_cast<void*>(NULL)); 219 memset(ptr, 'G', kDataSize); 220 221 memory.Close(); 222 223 EXPECT_EQ(ptr, memory.memory()); 224 EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); 225 226 for (size_t i = 0; i < kDataSize; i++) { 227 EXPECT_EQ('G', ptr[i]); 228 } 229 230 memory.Unmap(); 231 EXPECT_EQ(nullptr, memory.memory()); 232 } 233 234 #if !defined(OS_MACOSX) 235 // Create a set of N threads to each open a shared memory segment and write to 236 // it. Verify that they are always reading/writing consistent data. 237 TEST(SharedMemoryTest, MultipleThreads) { 238 const int kNumThreads = 5; 239 240 MultipleThreadMain::CleanUp(); 241 // On POSIX we have a problem when 2 threads try to create the shmem 242 // (a file) at exactly the same time, since create both creates the 243 // file and zerofills it. We solve the problem for this unit test 244 // (make it not flaky) by starting with 1 thread, then 245 // intentionally don't clean up its shmem before running with 246 // kNumThreads. 247 248 int threadcounts[] = { 1, kNumThreads }; 249 for (size_t i = 0; i < arraysize(threadcounts); i++) { 250 int numthreads = threadcounts[i]; 251 std::unique_ptr<PlatformThreadHandle[]> thread_handles; 252 std::unique_ptr<MultipleThreadMain* []> thread_delegates; 253 254 thread_handles.reset(new PlatformThreadHandle[numthreads]); 255 thread_delegates.reset(new MultipleThreadMain*[numthreads]); 256 257 // Spawn the threads. 258 for (int16_t index = 0; index < numthreads; index++) { 259 PlatformThreadHandle pth; 260 thread_delegates[index] = new MultipleThreadMain(index); 261 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 262 thread_handles[index] = pth; 263 } 264 265 // Wait for the threads to finish. 266 for (int index = 0; index < numthreads; index++) { 267 PlatformThread::Join(thread_handles[index]); 268 delete thread_delegates[index]; 269 } 270 } 271 MultipleThreadMain::CleanUp(); 272 } 273 #endif 274 275 // Allocate private (unique) shared memory with an empty string for a 276 // name. Make sure several of them don't point to the same thing as 277 // we might expect if the names are equal. 278 TEST(SharedMemoryTest, AnonymousPrivate) { 279 int i, j; 280 int count = 4; 281 bool rv; 282 const uint32_t kDataSize = 8192; 283 284 std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]); 285 std::unique_ptr<int* []> pointers(new int*[count]); 286 ASSERT_TRUE(memories.get()); 287 ASSERT_TRUE(pointers.get()); 288 289 for (i = 0; i < count; i++) { 290 rv = memories[i].CreateAndMapAnonymous(kDataSize); 291 EXPECT_TRUE(rv); 292 int* ptr = static_cast<int*>(memories[i].memory()); 293 EXPECT_TRUE(ptr); 294 pointers[i] = ptr; 295 } 296 297 for (i = 0; i < count; i++) { 298 // zero out the first int in each except for i; for that one, make it 100. 299 for (j = 0; j < count; j++) { 300 if (i == j) 301 pointers[j][0] = 100; 302 else 303 pointers[j][0] = 0; 304 } 305 // make sure there is no bleeding of the 100 into the other pointers 306 for (j = 0; j < count; j++) { 307 if (i == j) 308 EXPECT_EQ(100, pointers[j][0]); 309 else 310 EXPECT_EQ(0, pointers[j][0]); 311 } 312 } 313 314 for (int i = 0; i < count; i++) { 315 memories[i].Close(); 316 } 317 } 318 319 TEST(SharedMemoryTest, ShareReadOnly) { 320 StringPiece contents = "Hello World"; 321 322 SharedMemory writable_shmem; 323 SharedMemoryCreateOptions options; 324 options.size = contents.size(); 325 options.share_read_only = true; 326 #if defined(OS_MACOSX) && !defined(OS_IOS) 327 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 328 options.type = SharedMemoryHandle::POSIX; 329 #endif 330 ASSERT_TRUE(writable_shmem.Create(options)); 331 ASSERT_TRUE(writable_shmem.Map(options.size)); 332 memcpy(writable_shmem.memory(), contents.data(), contents.size()); 333 EXPECT_TRUE(writable_shmem.Unmap()); 334 335 SharedMemoryHandle readonly_handle; 336 ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(), 337 &readonly_handle)); 338 SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true); 339 340 ASSERT_TRUE(readonly_shmem.Map(contents.size())); 341 EXPECT_EQ(contents, 342 StringPiece(static_cast<const char*>(readonly_shmem.memory()), 343 contents.size())); 344 EXPECT_TRUE(readonly_shmem.Unmap()); 345 346 // Make sure the writable instance is still writable. 347 ASSERT_TRUE(writable_shmem.Map(contents.size())); 348 StringPiece new_contents = "Goodbye"; 349 memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size()); 350 EXPECT_EQ(new_contents, 351 StringPiece(static_cast<const char*>(writable_shmem.memory()), 352 new_contents.size())); 353 354 // We'd like to check that if we send the read-only segment to another 355 // process, then that other process can't reopen it read/write. (Since that 356 // would be a security hole.) Setting up multiple processes is hard in a 357 // unittest, so this test checks that the *current* process can't reopen the 358 // segment read/write. I think the test here is stronger than we actually 359 // care about, but there's a remote possibility that sending a file over a 360 // pipe would transform it into read/write. 361 SharedMemoryHandle handle = readonly_shmem.handle(); 362 363 #if defined(OS_ANDROID) 364 // The "read-only" handle is still writable on Android: 365 // http://crbug.com/320865 366 (void)handle; 367 #elif defined(OS_POSIX) 368 int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle); 369 EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE) 370 << "The descriptor itself should be read-only."; 371 372 errno = 0; 373 void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE, 374 MAP_SHARED, handle_fd, 0); 375 int mmap_errno = errno; 376 EXPECT_EQ(MAP_FAILED, writable) 377 << "It shouldn't be possible to re-mmap the descriptor writable."; 378 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); 379 if (writable != MAP_FAILED) 380 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); 381 382 #elif defined(OS_WIN) 383 EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0)) 384 << "Shouldn't be able to map memory writable."; 385 386 HANDLE temp_handle; 387 BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 388 GetCurrentProcess(), &temp_handle, 389 FILE_MAP_ALL_ACCESS, false, 0); 390 EXPECT_EQ(FALSE, rv) 391 << "Shouldn't be able to duplicate the handle into a writable one."; 392 if (rv) 393 win::ScopedHandle writable_handle(temp_handle); 394 rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 395 GetCurrentProcess(), &temp_handle, FILE_MAP_READ, 396 false, 0); 397 EXPECT_EQ(TRUE, rv) 398 << "Should be able to duplicate the handle into a readable one."; 399 if (rv) 400 win::ScopedHandle writable_handle(temp_handle); 401 #else 402 #error Unexpected platform; write a test that tries to make 'handle' writable. 403 #endif // defined(OS_POSIX) || defined(OS_WIN) 404 } 405 406 TEST(SharedMemoryTest, ShareToSelf) { 407 StringPiece contents = "Hello World"; 408 409 SharedMemory shmem; 410 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); 411 memcpy(shmem.memory(), contents.data(), contents.size()); 412 EXPECT_TRUE(shmem.Unmap()); 413 414 SharedMemoryHandle shared_handle; 415 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 416 #if defined(OS_WIN) 417 ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 418 #endif 419 SharedMemory shared(shared_handle, /*readonly=*/false); 420 421 ASSERT_TRUE(shared.Map(contents.size())); 422 EXPECT_EQ( 423 contents, 424 StringPiece(static_cast<const char*>(shared.memory()), contents.size())); 425 426 shared_handle = SharedMemoryHandle(); 427 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 428 #if defined(OS_WIN) 429 ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 430 #endif 431 SharedMemory readonly(shared_handle, /*readonly=*/true); 432 433 ASSERT_TRUE(readonly.Map(contents.size())); 434 EXPECT_EQ(contents, 435 StringPiece(static_cast<const char*>(readonly.memory()), 436 contents.size())); 437 } 438 439 TEST(SharedMemoryTest, MapAt) { 440 ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t)); 441 const size_t kCount = SysInfo::VMAllocationGranularity(); 442 const size_t kDataSize = kCount * sizeof(uint32_t); 443 444 SharedMemory memory; 445 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 446 uint32_t* ptr = static_cast<uint32_t*>(memory.memory()); 447 ASSERT_NE(ptr, static_cast<void*>(NULL)); 448 449 for (size_t i = 0; i < kCount; ++i) { 450 ptr[i] = i; 451 } 452 453 memory.Unmap(); 454 455 off_t offset = SysInfo::VMAllocationGranularity(); 456 ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset)); 457 offset /= sizeof(uint32_t); 458 ptr = static_cast<uint32_t*>(memory.memory()); 459 ASSERT_NE(ptr, static_cast<void*>(NULL)); 460 for (size_t i = offset; i < kCount; ++i) { 461 EXPECT_EQ(ptr[i - offset], i); 462 } 463 } 464 465 TEST(SharedMemoryTest, MapTwice) { 466 const uint32_t kDataSize = 1024; 467 SharedMemory memory; 468 bool rv = memory.CreateAndMapAnonymous(kDataSize); 469 EXPECT_TRUE(rv); 470 471 void* old_address = memory.memory(); 472 473 rv = memory.Map(kDataSize); 474 EXPECT_FALSE(rv); 475 EXPECT_EQ(old_address, memory.memory()); 476 } 477 478 #if defined(OS_POSIX) 479 // This test is not applicable for iOS (crbug.com/399384). 480 #if !defined(OS_IOS) 481 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC. 482 TEST(SharedMemoryTest, AnonymousExecutable) { 483 const uint32_t kTestSize = 1 << 16; 484 485 SharedMemory shared_memory; 486 SharedMemoryCreateOptions options; 487 options.size = kTestSize; 488 options.executable = true; 489 #if defined(OS_MACOSX) && !defined(OS_IOS) 490 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 491 options.type = SharedMemoryHandle::POSIX; 492 #endif 493 494 EXPECT_TRUE(shared_memory.Create(options)); 495 EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size())); 496 497 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(), 498 PROT_READ | PROT_EXEC)); 499 } 500 #endif // !defined(OS_IOS) 501 502 // Android supports a different permission model than POSIX for its "ashmem" 503 // shared memory implementation. So the tests about file permissions are not 504 // included on Android. 505 #if !defined(OS_ANDROID) 506 507 // Set a umask and restore the old mask on destruction. 508 class ScopedUmaskSetter { 509 public: 510 explicit ScopedUmaskSetter(mode_t target_mask) { 511 old_umask_ = umask(target_mask); 512 } 513 ~ScopedUmaskSetter() { umask(old_umask_); } 514 private: 515 mode_t old_umask_; 516 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 517 }; 518 519 // Create a shared memory object, check its permissions. 520 TEST(SharedMemoryTest, FilePermissionsAnonymous) { 521 const uint32_t kTestSize = 1 << 8; 522 523 SharedMemory shared_memory; 524 SharedMemoryCreateOptions options; 525 options.size = kTestSize; 526 #if defined(OS_MACOSX) && !defined(OS_IOS) 527 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 528 options.type = SharedMemoryHandle::POSIX; 529 #endif 530 // Set a file mode creation mask that gives all permissions. 531 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 532 533 EXPECT_TRUE(shared_memory.Create(options)); 534 535 int shm_fd = 536 SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 537 struct stat shm_stat; 538 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); 539 // Neither the group, nor others should be able to read the shared memory 540 // file. 541 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 542 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 543 } 544 545 // Create a shared memory object, check its permissions. 546 TEST(SharedMemoryTest, FilePermissionsNamed) { 547 const uint32_t kTestSize = 1 << 8; 548 549 SharedMemory shared_memory; 550 SharedMemoryCreateOptions options; 551 options.size = kTestSize; 552 #if defined(OS_MACOSX) && !defined(OS_IOS) 553 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 554 options.type = SharedMemoryHandle::POSIX; 555 #endif 556 557 // Set a file mode creation mask that gives all permissions. 558 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 559 560 EXPECT_TRUE(shared_memory.Create(options)); 561 562 int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 563 struct stat shm_stat; 564 EXPECT_EQ(0, fstat(fd, &shm_stat)); 565 // Neither the group, nor others should have been able to open the shared 566 // memory file while its name existed. 567 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 568 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 569 } 570 #endif // !defined(OS_ANDROID) 571 572 #endif // defined(OS_POSIX) 573 574 // Map() will return addresses which are aligned to the platform page size, this 575 // varies from platform to platform though. Since we'd like to advertise a 576 // minimum alignment that callers can count on, test for it here. 577 TEST(SharedMemoryTest, MapMinimumAlignment) { 578 static const int kDataSize = 8192; 579 580 SharedMemory shared_memory; 581 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); 582 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( 583 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 584 shared_memory.Close(); 585 } 586 587 #if defined(OS_WIN) 588 TEST(SharedMemoryTest, UnsafeImageSection) { 589 const char kTestSectionName[] = "UnsafeImageSection"; 590 wchar_t path[MAX_PATH]; 591 EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U); 592 593 // Map the current executable image to save us creating a new PE file on disk. 594 base::win::ScopedHandle file_handle(::CreateFile( 595 path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); 596 EXPECT_TRUE(file_handle.IsValid()); 597 base::win::ScopedHandle section_handle( 598 ::CreateFileMappingA(file_handle.Get(), nullptr, 599 PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName)); 600 EXPECT_TRUE(section_handle.IsValid()); 601 602 // Check direct opening by name, from handle and duplicated from handle. 603 SharedMemory shared_memory_open; 604 EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true)); 605 EXPECT_FALSE(shared_memory_open.Map(1)); 606 EXPECT_EQ(nullptr, shared_memory_open.memory()); 607 608 SharedMemory shared_memory_handle_local( 609 SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true); 610 EXPECT_FALSE(shared_memory_handle_local.Map(1)); 611 EXPECT_EQ(nullptr, shared_memory_handle_local.memory()); 612 613 // Check that a handle without SECTION_QUERY also can't be mapped as it can't 614 // be checked. 615 SharedMemory shared_memory_handle_dummy; 616 SharedMemoryCreateOptions options; 617 options.size = 0x1000; 618 EXPECT_TRUE(shared_memory_handle_dummy.Create(options)); 619 HANDLE handle_no_query; 620 EXPECT_TRUE(::DuplicateHandle( 621 ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(), 622 ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0)); 623 SharedMemory shared_memory_handle_no_query( 624 SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true); 625 EXPECT_FALSE(shared_memory_handle_no_query.Map(1)); 626 EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory()); 627 } 628 #endif // defined(OS_WIN) 629 630 // iOS does not allow multiple processes. 631 // Android ashmem does not support named shared memory. 632 // Mac SharedMemory does not support named shared memory. crbug.com/345734 633 #if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 634 // On POSIX it is especially important we test shmem across processes, 635 // not just across threads. But the test is enabled on all platforms. 636 class SharedMemoryProcessTest : public MultiProcessTest { 637 public: 638 static void CleanUp() { 639 SharedMemory memory; 640 memory.Delete(s_test_name_); 641 } 642 643 static int TaskTestMain() { 644 int errors = 0; 645 SharedMemory memory; 646 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 647 EXPECT_TRUE(rv); 648 if (rv != true) 649 errors++; 650 rv = memory.Map(s_data_size_); 651 EXPECT_TRUE(rv); 652 if (rv != true) 653 errors++; 654 int* ptr = static_cast<int*>(memory.memory()); 655 656 // This runs concurrently in multiple processes. Writes need to be atomic. 657 subtle::Barrier_AtomicIncrement(ptr, 1); 658 memory.Close(); 659 return errors; 660 } 661 662 static const char s_test_name_[]; 663 static const uint32_t s_data_size_; 664 }; 665 666 const char SharedMemoryProcessTest::s_test_name_[] = "MPMem"; 667 const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024; 668 669 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { 670 const int kNumTasks = 5; 671 672 SharedMemoryProcessTest::CleanUp(); 673 674 // Create a shared memory region. Set the first word to 0. 675 SharedMemory memory; 676 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 677 ASSERT_TRUE(rv); 678 rv = memory.Map(s_data_size_); 679 ASSERT_TRUE(rv); 680 int* ptr = static_cast<int*>(memory.memory()); 681 *ptr = 0; 682 683 // Start |kNumTasks| processes, each of which atomically increments the first 684 // word by 1. 685 SpawnChildResult children[kNumTasks]; 686 for (int index = 0; index < kNumTasks; ++index) { 687 children[index] = SpawnChild("SharedMemoryTestMain"); 688 ASSERT_TRUE(children[index].process.IsValid()); 689 } 690 691 // Check that each process exited correctly. 692 int exit_code = 0; 693 for (int index = 0; index < kNumTasks; ++index) { 694 EXPECT_TRUE(children[index].process.WaitForExit(&exit_code)); 695 EXPECT_EQ(0, exit_code); 696 } 697 698 // Check that the shared memory region reflects |kNumTasks| increments. 699 ASSERT_EQ(kNumTasks, *ptr); 700 701 memory.Close(); 702 SharedMemoryProcessTest::CleanUp(); 703 } 704 705 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { 706 return SharedMemoryProcessTest::TaskTestMain(); 707 } 708 #endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 709 710 } // namespace base 711