Home | History | Annotate | Download | only in memory
      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/base_switches.h"
     14 #include "base/bind.h"
     15 #include "base/command_line.h"
     16 #include "base/logging.h"
     17 #include "base/macros.h"
     18 #include "base/memory/shared_memory_handle.h"
     19 #include "base/process/kill.h"
     20 #include "base/rand_util.h"
     21 #include "base/strings/string_number_conversions.h"
     22 #include "base/strings/string_piece.h"
     23 #include "base/strings/string_util.h"
     24 #include "base/sys_info.h"
     25 #include "base/test/multiprocess_test.h"
     26 #include "base/threading/platform_thread.h"
     27 #include "base/time/time.h"
     28 #include "base/unguessable_token.h"
     29 #include "build/build_config.h"
     30 #include "testing/gtest/include/gtest/gtest.h"
     31 #include "testing/multiprocess_func_list.h"
     32 
     33 #if defined(OS_ANDROID)
     34 #include "base/callback.h"
     35 #endif
     36 
     37 #if defined(OS_POSIX)
     38 #include <errno.h>
     39 #include <fcntl.h>
     40 #include <sys/mman.h>
     41 #include <sys/stat.h>
     42 #include <sys/types.h>
     43 #include <unistd.h>
     44 #endif
     45 
     46 #if defined(OS_LINUX)
     47 #include <sys/syscall.h>
     48 #endif
     49 
     50 #if defined(OS_WIN)
     51 #include "base/win/scoped_handle.h"
     52 #endif
     53 
     54 #if defined(OS_FUCHSIA)
     55 #include <lib/zx/vmar.h>
     56 #include <lib/zx/vmo.h>
     57 #endif
     58 
     59 namespace base {
     60 
     61 namespace {
     62 
     63 #if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
     64 // Each thread will open the shared memory.  Each thread will take a different 4
     65 // byte int pointer, and keep changing it, with some small pauses in between.
     66 // Verify that each thread's value in the shared memory is always correct.
     67 class MultipleThreadMain : public PlatformThread::Delegate {
     68  public:
     69   explicit MultipleThreadMain(int16_t id) : id_(id) {}
     70   ~MultipleThreadMain() override = default;
     71 
     72   static void CleanUp() {
     73     SharedMemory memory;
     74     memory.Delete(s_test_name_);
     75   }
     76 
     77   // PlatformThread::Delegate interface.
     78   void ThreadMain() override {
     79     const uint32_t kDataSize = 1024;
     80     SharedMemory memory;
     81     bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
     82     EXPECT_TRUE(rv);
     83     rv = memory.Map(kDataSize);
     84     EXPECT_TRUE(rv);
     85     int* ptr = static_cast<int*>(memory.memory()) + id_;
     86     EXPECT_EQ(0, *ptr);
     87 
     88     for (int idx = 0; idx < 100; idx++) {
     89       *ptr = idx;
     90       PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
     91       EXPECT_EQ(*ptr, idx);
     92     }
     93     // Reset back to 0 for the next test that uses the same name.
     94     *ptr = 0;
     95 
     96     memory.Close();
     97   }
     98 
     99  private:
    100   int16_t id_;
    101 
    102   static const char s_test_name_[];
    103 
    104   DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
    105 };
    106 
    107 const char MultipleThreadMain::s_test_name_[] =
    108     "SharedMemoryOpenThreadTest";
    109 #endif  // !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
    110 
    111 enum class Mode {
    112   Default,
    113 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    114   DisableDevShm = 1,
    115 #endif
    116 };
    117 
    118 class SharedMemoryTest : public ::testing::TestWithParam<Mode> {
    119  public:
    120   void SetUp() override {
    121     switch (GetParam()) {
    122       case Mode::Default:
    123         break;
    124 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    125       case Mode::DisableDevShm:
    126         CommandLine* cmdline = CommandLine::ForCurrentProcess();
    127         cmdline->AppendSwitch(switches::kDisableDevShmUsage);
    128         break;
    129 #endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
    130     }
    131   }
    132 };
    133 
    134 }  // namespace
    135 
    136 // Android/Mac/Fuchsia doesn't support SharedMemory::Open/Delete/
    137 // CreateNamedDeprecated(openExisting=true)
    138 #if !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
    139 
    140 TEST_P(SharedMemoryTest, OpenClose) {
    141   const uint32_t kDataSize = 1024;
    142   std::string test_name = "SharedMemoryOpenCloseTest";
    143 
    144   // Open two handles to a memory segment, confirm that they are mapped
    145   // separately yet point to the same space.
    146   SharedMemory memory1;
    147   bool rv = memory1.Delete(test_name);
    148   EXPECT_TRUE(rv);
    149   rv = memory1.Delete(test_name);
    150   EXPECT_TRUE(rv);
    151   rv = memory1.Open(test_name, false);
    152   EXPECT_FALSE(rv);
    153   rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
    154   EXPECT_TRUE(rv);
    155   rv = memory1.Map(kDataSize);
    156   EXPECT_TRUE(rv);
    157   SharedMemory memory2;
    158   rv = memory2.Open(test_name, false);
    159   EXPECT_TRUE(rv);
    160   rv = memory2.Map(kDataSize);
    161   EXPECT_TRUE(rv);
    162   EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.
    163 
    164   // Make sure we don't segfault. (it actually happened!)
    165   ASSERT_NE(memory1.memory(), static_cast<void*>(nullptr));
    166   ASSERT_NE(memory2.memory(), static_cast<void*>(nullptr));
    167 
    168   // Write data to the first memory segment, verify contents of second.
    169   memset(memory1.memory(), '1', kDataSize);
    170   EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
    171 
    172   // Close the first memory segment, and verify the second has the right data.
    173   memory1.Close();
    174   char* start_ptr = static_cast<char*>(memory2.memory());
    175   char* end_ptr = start_ptr + kDataSize;
    176   for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
    177     EXPECT_EQ(*ptr, '1');
    178 
    179   // Close the second memory segment.
    180   memory2.Close();
    181 
    182   rv = memory1.Delete(test_name);
    183   EXPECT_TRUE(rv);
    184   rv = memory2.Delete(test_name);
    185   EXPECT_TRUE(rv);
    186 }
    187 
    188 TEST_P(SharedMemoryTest, OpenExclusive) {
    189   const uint32_t kDataSize = 1024;
    190   const uint32_t kDataSize2 = 2048;
    191   std::ostringstream test_name_stream;
    192   test_name_stream << "SharedMemoryOpenExclusiveTest."
    193                    << Time::Now().ToDoubleT();
    194   std::string test_name = test_name_stream.str();
    195 
    196   // Open two handles to a memory segment and check that
    197   // open_existing_deprecated works as expected.
    198   SharedMemory memory1;
    199   bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
    200   EXPECT_TRUE(rv);
    201 
    202   // Memory1 knows it's size because it created it.
    203   EXPECT_EQ(memory1.requested_size(), kDataSize);
    204 
    205   rv = memory1.Map(kDataSize);
    206   EXPECT_TRUE(rv);
    207 
    208   // The mapped memory1 must be at least the size we asked for.
    209   EXPECT_GE(memory1.mapped_size(), kDataSize);
    210 
    211   // The mapped memory1 shouldn't exceed rounding for allocation granularity.
    212   EXPECT_LT(memory1.mapped_size(),
    213             kDataSize + SysInfo::VMAllocationGranularity());
    214 
    215   memset(memory1.memory(), 'G', kDataSize);
    216 
    217   SharedMemory memory2;
    218   // Should not be able to create if openExisting is false.
    219   rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2);
    220   EXPECT_FALSE(rv);
    221 
    222   // Should be able to create with openExisting true.
    223   rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
    224   EXPECT_TRUE(rv);
    225 
    226   // Memory2 shouldn't know the size because we didn't create it.
    227   EXPECT_EQ(memory2.requested_size(), 0U);
    228 
    229   // We should be able to map the original size.
    230   rv = memory2.Map(kDataSize);
    231   EXPECT_TRUE(rv);
    232 
    233   // The mapped memory2 must be at least the size of the original.
    234   EXPECT_GE(memory2.mapped_size(), kDataSize);
    235 
    236   // The mapped memory2 shouldn't exceed rounding for allocation granularity.
    237   EXPECT_LT(memory2.mapped_size(),
    238             kDataSize2 + SysInfo::VMAllocationGranularity());
    239 
    240   // Verify that opening memory2 didn't truncate or delete memory 1.
    241   char* start_ptr = static_cast<char*>(memory2.memory());
    242   char* end_ptr = start_ptr + kDataSize;
    243   for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
    244     EXPECT_EQ(*ptr, 'G');
    245   }
    246 
    247   memory1.Close();
    248   memory2.Close();
    249 
    250   rv = memory1.Delete(test_name);
    251   EXPECT_TRUE(rv);
    252 }
    253 #endif  // !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
    254 
    255 // Check that memory is still mapped after its closed.
    256 TEST_P(SharedMemoryTest, CloseNoUnmap) {
    257   const size_t kDataSize = 4096;
    258 
    259   SharedMemory memory;
    260   ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
    261   char* ptr = static_cast<char*>(memory.memory());
    262   ASSERT_NE(ptr, static_cast<void*>(nullptr));
    263   memset(ptr, 'G', kDataSize);
    264 
    265   memory.Close();
    266 
    267   EXPECT_EQ(ptr, memory.memory());
    268   EXPECT_TRUE(!memory.handle().IsValid());
    269 
    270   for (size_t i = 0; i < kDataSize; i++) {
    271     EXPECT_EQ('G', ptr[i]);
    272   }
    273 
    274   memory.Unmap();
    275   EXPECT_EQ(nullptr, memory.memory());
    276 }
    277 
    278 #if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
    279 // Create a set of N threads to each open a shared memory segment and write to
    280 // it. Verify that they are always reading/writing consistent data.
    281 TEST_P(SharedMemoryTest, MultipleThreads) {
    282   const int kNumThreads = 5;
    283 
    284   MultipleThreadMain::CleanUp();
    285   // On POSIX we have a problem when 2 threads try to create the shmem
    286   // (a file) at exactly the same time, since create both creates the
    287   // file and zerofills it.  We solve the problem for this unit test
    288   // (make it not flaky) by starting with 1 thread, then
    289   // intentionally don't clean up its shmem before running with
    290   // kNumThreads.
    291 
    292   int threadcounts[] = { 1, kNumThreads };
    293   for (size_t i = 0; i < arraysize(threadcounts); i++) {
    294     int numthreads = threadcounts[i];
    295     std::unique_ptr<PlatformThreadHandle[]> thread_handles;
    296     std::unique_ptr<MultipleThreadMain* []> thread_delegates;
    297 
    298     thread_handles.reset(new PlatformThreadHandle[numthreads]);
    299     thread_delegates.reset(new MultipleThreadMain*[numthreads]);
    300 
    301     // Spawn the threads.
    302     for (int16_t index = 0; index < numthreads; index++) {
    303       PlatformThreadHandle pth;
    304       thread_delegates[index] = new MultipleThreadMain(index);
    305       EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
    306       thread_handles[index] = pth;
    307     }
    308 
    309     // Wait for the threads to finish.
    310     for (int index = 0; index < numthreads; index++) {
    311       PlatformThread::Join(thread_handles[index]);
    312       delete thread_delegates[index];
    313     }
    314   }
    315   MultipleThreadMain::CleanUp();
    316 }
    317 #endif
    318 
    319 // Allocate private (unique) shared memory with an empty string for a
    320 // name.  Make sure several of them don't point to the same thing as
    321 // we might expect if the names are equal.
    322 TEST_P(SharedMemoryTest, AnonymousPrivate) {
    323   int i, j;
    324   int count = 4;
    325   bool rv;
    326   const uint32_t kDataSize = 8192;
    327 
    328   std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]);
    329   std::unique_ptr<int* []> pointers(new int*[count]);
    330   ASSERT_TRUE(memories.get());
    331   ASSERT_TRUE(pointers.get());
    332 
    333   for (i = 0; i < count; i++) {
    334     rv = memories[i].CreateAndMapAnonymous(kDataSize);
    335     EXPECT_TRUE(rv);
    336     int* ptr = static_cast<int*>(memories[i].memory());
    337     EXPECT_TRUE(ptr);
    338     pointers[i] = ptr;
    339   }
    340 
    341   for (i = 0; i < count; i++) {
    342     // zero out the first int in each except for i; for that one, make it 100.
    343     for (j = 0; j < count; j++) {
    344       if (i == j)
    345         pointers[j][0] = 100;
    346       else
    347         pointers[j][0] = 0;
    348     }
    349     // make sure there is no bleeding of the 100 into the other pointers
    350     for (j = 0; j < count; j++) {
    351       if (i == j)
    352         EXPECT_EQ(100, pointers[j][0]);
    353       else
    354         EXPECT_EQ(0, pointers[j][0]);
    355     }
    356   }
    357 
    358   for (int i = 0; i < count; i++) {
    359     memories[i].Close();
    360   }
    361 }
    362 
    363 TEST_P(SharedMemoryTest, GetReadOnlyHandle) {
    364   StringPiece contents = "Hello World";
    365 
    366   SharedMemory writable_shmem;
    367   SharedMemoryCreateOptions options;
    368   options.size = contents.size();
    369   options.share_read_only = true;
    370 #if defined(OS_MACOSX) && !defined(OS_IOS)
    371   // The Mach functionality is tested in shared_memory_mac_unittest.cc.
    372   options.type = SharedMemoryHandle::POSIX;
    373 #endif
    374   ASSERT_TRUE(writable_shmem.Create(options));
    375   ASSERT_TRUE(writable_shmem.Map(options.size));
    376   memcpy(writable_shmem.memory(), contents.data(), contents.size());
    377   EXPECT_TRUE(writable_shmem.Unmap());
    378 
    379   SharedMemoryHandle readonly_handle = writable_shmem.GetReadOnlyHandle();
    380   EXPECT_EQ(writable_shmem.handle().GetGUID(), readonly_handle.GetGUID());
    381   EXPECT_EQ(writable_shmem.handle().GetSize(), readonly_handle.GetSize());
    382   ASSERT_TRUE(readonly_handle.IsValid());
    383   SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
    384 
    385   ASSERT_TRUE(readonly_shmem.Map(contents.size()));
    386   EXPECT_EQ(contents,
    387             StringPiece(static_cast<const char*>(readonly_shmem.memory()),
    388                         contents.size()));
    389   EXPECT_TRUE(readonly_shmem.Unmap());
    390 
    391 #if defined(OS_ANDROID)
    392   // On Android, mapping a region through a read-only descriptor makes the
    393   // region read-only. Any writable mapping attempt should fail.
    394   ASSERT_FALSE(writable_shmem.Map(contents.size()));
    395 #else
    396   // Make sure the writable instance is still writable.
    397   ASSERT_TRUE(writable_shmem.Map(contents.size()));
    398   StringPiece new_contents = "Goodbye";
    399   memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
    400   EXPECT_EQ(new_contents,
    401             StringPiece(static_cast<const char*>(writable_shmem.memory()),
    402                         new_contents.size()));
    403 #endif
    404 
    405   // We'd like to check that if we send the read-only segment to another
    406   // process, then that other process can't reopen it read/write.  (Since that
    407   // would be a security hole.)  Setting up multiple processes is hard in a
    408   // unittest, so this test checks that the *current* process can't reopen the
    409   // segment read/write.  I think the test here is stronger than we actually
    410   // care about, but there's a remote possibility that sending a file over a
    411   // pipe would transform it into read/write.
    412   SharedMemoryHandle handle = readonly_shmem.handle();
    413 
    414 #if defined(OS_ANDROID)
    415   // The "read-only" handle is still writable on Android:
    416   // http://crbug.com/320865
    417   (void)handle;
    418 #elif defined(OS_FUCHSIA)
    419   uintptr_t addr;
    420   EXPECT_NE(ZX_OK, zx::vmar::root_self()->map(
    421                        0, *zx::unowned_vmo(handle.GetHandle()), 0,
    422                        contents.size(), ZX_VM_FLAG_PERM_WRITE, &addr))
    423       << "Shouldn't be able to map as writable.";
    424 
    425   zx::vmo duped_handle;
    426   EXPECT_NE(ZX_OK, zx::unowned_vmo(handle.GetHandle())
    427                        ->duplicate(ZX_RIGHT_WRITE, &duped_handle))
    428       << "Shouldn't be able to duplicate the handle into a writable one.";
    429 
    430   EXPECT_EQ(ZX_OK, zx::unowned_vmo(handle.GetHandle())
    431                        ->duplicate(ZX_RIGHT_READ, &duped_handle))
    432       << "Should be able to duplicate the handle into a readable one.";
    433 #elif defined(OS_POSIX)
    434   int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle);
    435   EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE)
    436       << "The descriptor itself should be read-only.";
    437 
    438   errno = 0;
    439   void* writable = mmap(nullptr, contents.size(), PROT_READ | PROT_WRITE,
    440                         MAP_SHARED, handle_fd, 0);
    441   int mmap_errno = errno;
    442   EXPECT_EQ(MAP_FAILED, writable)
    443       << "It shouldn't be possible to re-mmap the descriptor writable.";
    444   EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
    445   if (writable != MAP_FAILED)
    446     EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
    447 
    448 #elif defined(OS_WIN)
    449   EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0))
    450       << "Shouldn't be able to map memory writable.";
    451 
    452   HANDLE temp_handle;
    453   BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
    454                               GetCurrentProcess(), &temp_handle,
    455                               FILE_MAP_ALL_ACCESS, false, 0);
    456   EXPECT_EQ(FALSE, rv)
    457       << "Shouldn't be able to duplicate the handle into a writable one.";
    458   if (rv)
    459     win::ScopedHandle writable_handle(temp_handle);
    460   rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
    461                          GetCurrentProcess(), &temp_handle, FILE_MAP_READ,
    462                          false, 0);
    463   EXPECT_EQ(TRUE, rv)
    464       << "Should be able to duplicate the handle into a readable one.";
    465   if (rv)
    466     win::ScopedHandle writable_handle(temp_handle);
    467 #else
    468 #error Unexpected platform; write a test that tries to make 'handle' writable.
    469 #endif  // defined(OS_POSIX) || defined(OS_WIN)
    470 }
    471 
    472 TEST_P(SharedMemoryTest, ShareToSelf) {
    473   StringPiece contents = "Hello World";
    474 
    475   SharedMemory shmem;
    476   ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
    477   memcpy(shmem.memory(), contents.data(), contents.size());
    478   EXPECT_TRUE(shmem.Unmap());
    479 
    480   SharedMemoryHandle shared_handle = shmem.handle().Duplicate();
    481   ASSERT_TRUE(shared_handle.IsValid());
    482   EXPECT_TRUE(shared_handle.OwnershipPassesToIPC());
    483   EXPECT_EQ(shared_handle.GetGUID(), shmem.handle().GetGUID());
    484   EXPECT_EQ(shared_handle.GetSize(), shmem.handle().GetSize());
    485   SharedMemory shared(shared_handle, /*readonly=*/false);
    486 
    487   ASSERT_TRUE(shared.Map(contents.size()));
    488   EXPECT_EQ(
    489       contents,
    490       StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
    491 
    492   shared_handle = shmem.handle().Duplicate();
    493   ASSERT_TRUE(shared_handle.IsValid());
    494   ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
    495   SharedMemory readonly(shared_handle, /*readonly=*/true);
    496 
    497   ASSERT_TRUE(readonly.Map(contents.size()));
    498   EXPECT_EQ(contents,
    499             StringPiece(static_cast<const char*>(readonly.memory()),
    500                         contents.size()));
    501 }
    502 
    503 TEST_P(SharedMemoryTest, ShareWithMultipleInstances) {
    504   static const StringPiece kContents = "Hello World";
    505 
    506   SharedMemory shmem;
    507   ASSERT_TRUE(shmem.CreateAndMapAnonymous(kContents.size()));
    508   // We do not need to unmap |shmem| to let |shared| map.
    509   const StringPiece shmem_contents(static_cast<const char*>(shmem.memory()),
    510                                    shmem.requested_size());
    511 
    512   SharedMemoryHandle shared_handle = shmem.handle().Duplicate();
    513   ASSERT_TRUE(shared_handle.IsValid());
    514   SharedMemory shared(shared_handle, /*readonly=*/false);
    515   ASSERT_TRUE(shared.Map(kContents.size()));
    516   // The underlying shared memory is created by |shmem|, so both
    517   // |shared|.requested_size() and |readonly|.requested_size() are zero.
    518   ASSERT_EQ(0U, shared.requested_size());
    519   const StringPiece shared_contents(static_cast<const char*>(shared.memory()),
    520                                     shmem.requested_size());
    521 
    522   shared_handle = shmem.handle().Duplicate();
    523   ASSERT_TRUE(shared_handle.IsValid());
    524   ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
    525   SharedMemory readonly(shared_handle, /*readonly=*/true);
    526   ASSERT_TRUE(readonly.Map(kContents.size()));
    527   ASSERT_EQ(0U, readonly.requested_size());
    528   const StringPiece readonly_contents(
    529       static_cast<const char*>(readonly.memory()),
    530       shmem.requested_size());
    531 
    532   // |shmem| should be able to update the content.
    533   memcpy(shmem.memory(), kContents.data(), kContents.size());
    534 
    535   ASSERT_EQ(kContents, shmem_contents);
    536   ASSERT_EQ(kContents, shared_contents);
    537   ASSERT_EQ(kContents, readonly_contents);
    538 
    539   // |shared| should also be able to update the content.
    540   memcpy(shared.memory(), ToLowerASCII(kContents).c_str(), kContents.size());
    541 
    542   ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), shmem_contents);
    543   ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), shared_contents);
    544   ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), readonly_contents);
    545 }
    546 
    547 TEST_P(SharedMemoryTest, MapAt) {
    548   ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
    549   const size_t kCount = SysInfo::VMAllocationGranularity();
    550   const size_t kDataSize = kCount * sizeof(uint32_t);
    551 
    552   SharedMemory memory;
    553   ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
    554   uint32_t* ptr = static_cast<uint32_t*>(memory.memory());
    555   ASSERT_NE(ptr, static_cast<void*>(nullptr));
    556 
    557   for (size_t i = 0; i < kCount; ++i) {
    558     ptr[i] = i;
    559   }
    560 
    561   memory.Unmap();
    562 
    563   off_t offset = SysInfo::VMAllocationGranularity();
    564   ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
    565   offset /= sizeof(uint32_t);
    566   ptr = static_cast<uint32_t*>(memory.memory());
    567   ASSERT_NE(ptr, static_cast<void*>(nullptr));
    568   for (size_t i = offset; i < kCount; ++i) {
    569     EXPECT_EQ(ptr[i - offset], i);
    570   }
    571 }
    572 
    573 TEST_P(SharedMemoryTest, MapTwice) {
    574   const uint32_t kDataSize = 1024;
    575   SharedMemory memory;
    576   bool rv = memory.CreateAndMapAnonymous(kDataSize);
    577   EXPECT_TRUE(rv);
    578 
    579   void* old_address = memory.memory();
    580 
    581   rv = memory.Map(kDataSize);
    582   EXPECT_FALSE(rv);
    583   EXPECT_EQ(old_address, memory.memory());
    584 }
    585 
    586 #if defined(OS_POSIX)
    587 // This test is not applicable for iOS (crbug.com/399384).
    588 #if !defined(OS_IOS)
    589 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
    590 TEST_P(SharedMemoryTest, AnonymousExecutable) {
    591 #if defined(OS_LINUX)
    592   // On Chromecast both /dev/shm and /tmp are mounted with 'noexec' option,
    593   // which makes this test fail. But Chromecast doesn't use NaCL so we don't
    594   // need this.
    595   if (!IsPathExecutable(FilePath("/dev/shm")) &&
    596       !IsPathExecutable(FilePath("/tmp"))) {
    597     return;
    598   }
    599 #endif  // OS_LINUX
    600   const uint32_t kTestSize = 1 << 16;
    601 
    602   SharedMemory shared_memory;
    603   SharedMemoryCreateOptions options;
    604   options.size = kTestSize;
    605   options.executable = true;
    606 #if defined(OS_MACOSX) && !defined(OS_IOS)
    607   // The Mach functionality is tested in shared_memory_mac_unittest.cc.
    608   options.type = SharedMemoryHandle::POSIX;
    609 #endif
    610 
    611   EXPECT_TRUE(shared_memory.Create(options));
    612   EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
    613 
    614   EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
    615                         PROT_READ | PROT_EXEC));
    616 }
    617 #endif  // !defined(OS_IOS)
    618 
    619 #if defined(OS_ANDROID)
    620 // This test is restricted to Android since there is no way on other platforms
    621 // to guarantee that a region can never be mapped with PROT_EXEC. E.g. on
    622 // Linux, anonymous shared regions come from /dev/shm which can be mounted
    623 // without 'noexec'. In this case, anything can perform an mprotect() to
    624 // change the protection mask of a given page.
    625 TEST(SharedMemoryTest, AnonymousIsNotExecutableByDefault) {
    626   const uint32_t kTestSize = 1 << 16;
    627 
    628   SharedMemory shared_memory;
    629   SharedMemoryCreateOptions options;
    630   options.size = kTestSize;
    631 
    632   EXPECT_TRUE(shared_memory.Create(options));
    633   EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
    634 
    635   errno = 0;
    636   EXPECT_EQ(-1, mprotect(shared_memory.memory(), shared_memory.requested_size(),
    637                          PROT_READ | PROT_EXEC));
    638   EXPECT_EQ(EACCES, errno);
    639 }
    640 #endif  // OS_ANDROID
    641 
    642 // Android supports a different permission model than POSIX for its "ashmem"
    643 // shared memory implementation. So the tests about file permissions are not
    644 // included on Android. Fuchsia does not use a file-backed shared memory
    645 // implementation.
    646 
    647 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
    648 
    649 // Set a umask and restore the old mask on destruction.
    650 class ScopedUmaskSetter {
    651  public:
    652   explicit ScopedUmaskSetter(mode_t target_mask) {
    653     old_umask_ = umask(target_mask);
    654   }
    655   ~ScopedUmaskSetter() { umask(old_umask_); }
    656  private:
    657   mode_t old_umask_;
    658   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
    659 };
    660 
    661 // Create a shared memory object, check its permissions.
    662 TEST_P(SharedMemoryTest, FilePermissionsAnonymous) {
    663   const uint32_t kTestSize = 1 << 8;
    664 
    665   SharedMemory shared_memory;
    666   SharedMemoryCreateOptions options;
    667   options.size = kTestSize;
    668 #if defined(OS_MACOSX) && !defined(OS_IOS)
    669   // The Mach functionality is tested in shared_memory_mac_unittest.cc.
    670   options.type = SharedMemoryHandle::POSIX;
    671 #endif
    672   // Set a file mode creation mask that gives all permissions.
    673   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
    674 
    675   EXPECT_TRUE(shared_memory.Create(options));
    676 
    677   int shm_fd =
    678       SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
    679   struct stat shm_stat;
    680   EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
    681   // Neither the group, nor others should be able to read the shared memory
    682   // file.
    683   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
    684   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
    685 }
    686 
    687 // Create a shared memory object, check its permissions.
    688 TEST_P(SharedMemoryTest, FilePermissionsNamed) {
    689   const uint32_t kTestSize = 1 << 8;
    690 
    691   SharedMemory shared_memory;
    692   SharedMemoryCreateOptions options;
    693   options.size = kTestSize;
    694 #if defined(OS_MACOSX) && !defined(OS_IOS)
    695   // The Mach functionality is tested in shared_memory_mac_unittest.cc.
    696   options.type = SharedMemoryHandle::POSIX;
    697 #endif
    698 
    699   // Set a file mode creation mask that gives all permissions.
    700   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
    701 
    702   EXPECT_TRUE(shared_memory.Create(options));
    703 
    704   int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
    705   struct stat shm_stat;
    706   EXPECT_EQ(0, fstat(fd, &shm_stat));
    707   // Neither the group, nor others should have been able to open the shared
    708   // memory file while its name existed.
    709   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
    710   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
    711 }
    712 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
    713 
    714 #endif  // defined(OS_POSIX)
    715 
    716 // Map() will return addresses which are aligned to the platform page size, this
    717 // varies from platform to platform though.  Since we'd like to advertise a
    718 // minimum alignment that callers can count on, test for it here.
    719 TEST_P(SharedMemoryTest, MapMinimumAlignment) {
    720   static const int kDataSize = 8192;
    721 
    722   SharedMemory shared_memory;
    723   ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
    724   EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
    725       shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
    726   shared_memory.Close();
    727 }
    728 
    729 #if defined(OS_WIN)
    730 TEST_P(SharedMemoryTest, UnsafeImageSection) {
    731   const char kTestSectionName[] = "UnsafeImageSection";
    732   wchar_t path[MAX_PATH];
    733   EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
    734 
    735   // Map the current executable image to save us creating a new PE file on disk.
    736   base::win::ScopedHandle file_handle(::CreateFile(
    737       path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
    738   EXPECT_TRUE(file_handle.IsValid());
    739   base::win::ScopedHandle section_handle(
    740       ::CreateFileMappingA(file_handle.Get(), nullptr,
    741                            PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName));
    742   EXPECT_TRUE(section_handle.IsValid());
    743 
    744   // Check direct opening by name, from handle and duplicated from handle.
    745   SharedMemory shared_memory_open;
    746   EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true));
    747   EXPECT_FALSE(shared_memory_open.Map(1));
    748   EXPECT_EQ(nullptr, shared_memory_open.memory());
    749 
    750   SharedMemory shared_memory_handle_local(
    751       SharedMemoryHandle(section_handle.Take(), 1, UnguessableToken::Create()),
    752       true);
    753   EXPECT_FALSE(shared_memory_handle_local.Map(1));
    754   EXPECT_EQ(nullptr, shared_memory_handle_local.memory());
    755 
    756   // Check that a handle without SECTION_QUERY also can't be mapped as it can't
    757   // be checked.
    758   SharedMemory shared_memory_handle_dummy;
    759   SharedMemoryCreateOptions options;
    760   options.size = 0x1000;
    761   EXPECT_TRUE(shared_memory_handle_dummy.Create(options));
    762   HANDLE handle_no_query;
    763   EXPECT_TRUE(::DuplicateHandle(
    764       ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(),
    765       ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0));
    766   SharedMemory shared_memory_handle_no_query(
    767       SharedMemoryHandle(handle_no_query, options.size,
    768                          UnguessableToken::Create()),
    769       true);
    770   EXPECT_FALSE(shared_memory_handle_no_query.Map(1));
    771   EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory());
    772 }
    773 #endif  // defined(OS_WIN)
    774 
    775 // iOS does not allow multiple processes.
    776 // Android ashmem does not support named shared memory.
    777 // Fuchsia SharedMemory does not support named shared memory.
    778 // Mac SharedMemory does not support named shared memory. crbug.com/345734
    779 #if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \
    780     !defined(OS_FUCHSIA)
    781 // On POSIX it is especially important we test shmem across processes,
    782 // not just across threads.  But the test is enabled on all platforms.
    783 class SharedMemoryProcessTest : public MultiProcessTest {
    784  public:
    785   static void CleanUp() {
    786     SharedMemory memory;
    787     memory.Delete(s_test_name_);
    788   }
    789 
    790   static int TaskTestMain() {
    791     int errors = 0;
    792     SharedMemory memory;
    793     bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
    794     EXPECT_TRUE(rv);
    795     if (rv != true)
    796       errors++;
    797     rv = memory.Map(s_data_size_);
    798     EXPECT_TRUE(rv);
    799     if (rv != true)
    800       errors++;
    801     int* ptr = static_cast<int*>(memory.memory());
    802 
    803     // This runs concurrently in multiple processes. Writes need to be atomic.
    804     subtle::Barrier_AtomicIncrement(ptr, 1);
    805     memory.Close();
    806     return errors;
    807   }
    808 
    809   static const char s_test_name_[];
    810   static const uint32_t s_data_size_;
    811 };
    812 
    813 const char SharedMemoryProcessTest::s_test_name_[] = "MPMem";
    814 const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024;
    815 
    816 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
    817   const int kNumTasks = 5;
    818 
    819   SharedMemoryProcessTest::CleanUp();
    820 
    821   // Create a shared memory region. Set the first word to 0.
    822   SharedMemory memory;
    823   bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
    824   ASSERT_TRUE(rv);
    825   rv = memory.Map(s_data_size_);
    826   ASSERT_TRUE(rv);
    827   int* ptr = static_cast<int*>(memory.memory());
    828   *ptr = 0;
    829 
    830   // Start |kNumTasks| processes, each of which atomically increments the first
    831   // word by 1.
    832   Process processes[kNumTasks];
    833   for (int index = 0; index < kNumTasks; ++index) {
    834     processes[index] = SpawnChild("SharedMemoryTestMain");
    835     ASSERT_TRUE(processes[index].IsValid());
    836   }
    837 
    838   // Check that each process exited correctly.
    839   int exit_code = 0;
    840   for (int index = 0; index < kNumTasks; ++index) {
    841     EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
    842     EXPECT_EQ(0, exit_code);
    843   }
    844 
    845   // Check that the shared memory region reflects |kNumTasks| increments.
    846   ASSERT_EQ(kNumTasks, *ptr);
    847 
    848   memory.Close();
    849   SharedMemoryProcessTest::CleanUp();
    850 }
    851 
    852 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
    853   return SharedMemoryProcessTest::TaskTestMain();
    854 }
    855 #endif  // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) &&
    856         // !defined(OS_FUCHSIA)
    857 
    858 TEST_P(SharedMemoryTest, MappedId) {
    859   const uint32_t kDataSize = 1024;
    860   SharedMemory memory;
    861   SharedMemoryCreateOptions options;
    862   options.size = kDataSize;
    863 #if defined(OS_MACOSX) && !defined(OS_IOS)
    864   // The Mach functionality is tested in shared_memory_mac_unittest.cc.
    865   options.type = SharedMemoryHandle::POSIX;
    866 #endif
    867 
    868   EXPECT_TRUE(memory.Create(options));
    869   base::UnguessableToken id = memory.handle().GetGUID();
    870   EXPECT_FALSE(id.is_empty());
    871   EXPECT_TRUE(memory.mapped_id().is_empty());
    872 
    873   EXPECT_TRUE(memory.Map(kDataSize));
    874   EXPECT_EQ(id, memory.mapped_id());
    875 
    876   memory.Close();
    877   EXPECT_EQ(id, memory.mapped_id());
    878 
    879   memory.Unmap();
    880   EXPECT_TRUE(memory.mapped_id().is_empty());
    881 }
    882 
    883 INSTANTIATE_TEST_CASE_P(Default,
    884                         SharedMemoryTest,
    885                         ::testing::Values(Mode::Default));
    886 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    887 INSTANTIATE_TEST_CASE_P(SkipDevShm,
    888                         SharedMemoryTest,
    889                         ::testing::Values(Mode::DisableDevShm));
    890 #endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
    891 
    892 #if defined(OS_ANDROID)
    893 TEST(SharedMemoryTest, ReadOnlyRegions) {
    894   const uint32_t kDataSize = 1024;
    895   SharedMemory memory;
    896   SharedMemoryCreateOptions options;
    897   options.size = kDataSize;
    898   EXPECT_TRUE(memory.Create(options));
    899 
    900   EXPECT_FALSE(memory.handle().IsRegionReadOnly());
    901 
    902   // Check that it is possible to map the region directly from the fd.
    903   int region_fd = memory.handle().GetHandle();
    904   EXPECT_GE(region_fd, 0);
    905   void* address = mmap(nullptr, kDataSize, PROT_READ | PROT_WRITE, MAP_SHARED,
    906                        region_fd, 0);
    907   bool success = address && address != MAP_FAILED;
    908   ASSERT_TRUE(address);
    909   ASSERT_NE(address, MAP_FAILED);
    910   if (success) {
    911     EXPECT_EQ(0, munmap(address, kDataSize));
    912   }
    913 
    914   ASSERT_TRUE(memory.handle().SetRegionReadOnly());
    915   EXPECT_TRUE(memory.handle().IsRegionReadOnly());
    916 
    917   // Check that it is no longer possible to map the region read/write.
    918   errno = 0;
    919   address = mmap(nullptr, kDataSize, PROT_READ | PROT_WRITE, MAP_SHARED,
    920                  region_fd, 0);
    921   success = address && address != MAP_FAILED;
    922   ASSERT_FALSE(success);
    923   ASSERT_EQ(EPERM, errno);
    924   if (success) {
    925     EXPECT_EQ(0, munmap(address, kDataSize));
    926   }
    927 }
    928 
    929 TEST(SharedMemoryTest, ReadOnlyDescriptors) {
    930   const uint32_t kDataSize = 1024;
    931   SharedMemory memory;
    932   SharedMemoryCreateOptions options;
    933   options.size = kDataSize;
    934   EXPECT_TRUE(memory.Create(options));
    935 
    936   EXPECT_FALSE(memory.handle().IsRegionReadOnly());
    937 
    938   // Getting a read-only descriptor should not make the region read-only itself.
    939   SharedMemoryHandle ro_handle = memory.GetReadOnlyHandle();
    940   EXPECT_FALSE(memory.handle().IsRegionReadOnly());
    941 
    942   // Mapping a writable region from a read-only descriptor should not
    943   // be possible, it will DCHECK() in debug builds (see test below),
    944   // while returning false on release ones.
    945   {
    946     bool dcheck_fired = false;
    947     logging::ScopedLogAssertHandler log_assert(
    948         base::BindRepeating([](bool* flag, const char*, int, base::StringPiece,
    949                                base::StringPiece) { *flag = true; },
    950                             base::Unretained(&dcheck_fired)));
    951 
    952     SharedMemory rw_region(ro_handle.Duplicate(), /* read_only */ false);
    953     EXPECT_FALSE(rw_region.Map(kDataSize));
    954     EXPECT_EQ(DCHECK_IS_ON() ? true : false, dcheck_fired);
    955   }
    956 
    957   // Nor shall it turn the region read-only itself.
    958   EXPECT_FALSE(ro_handle.IsRegionReadOnly());
    959 
    960   // Mapping a read-only region from a read-only descriptor should work.
    961   SharedMemory ro_region(ro_handle.Duplicate(), /* read_only */ true);
    962   EXPECT_TRUE(ro_region.Map(kDataSize));
    963 
    964   // And it should turn the region read-only too.
    965   EXPECT_TRUE(ro_handle.IsRegionReadOnly());
    966   EXPECT_TRUE(memory.handle().IsRegionReadOnly());
    967   EXPECT_FALSE(memory.Map(kDataSize));
    968 
    969   ro_handle.Close();
    970 }
    971 
    972 #endif  // OS_ANDROID
    973 
    974 }  // namespace base
    975