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:
MultipleThreadMain(int16_t id)49   explicit MultipleThreadMain(int16_t id) : id_(id) {}
~MultipleThreadMain()50   ~MultipleThreadMain() override {}
51 
CleanUp()52   static void CleanUp() {
53     SharedMemory memory;
54     memory.Delete(s_test_name_);
55   }
56 
57   // PlatformThread::Delegate interface.
ThreadMain()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)
TEST(SharedMemoryTest,OpenClose)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 
TEST(SharedMemoryTest,OpenExclusive)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.
TEST(SharedMemoryTest,CloseNoUnmap)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.
TEST(SharedMemoryTest,MultipleThreads)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.
TEST(SharedMemoryTest,AnonymousPrivate)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 // The Mach functionality is tested in shared_memory_mac_unittest.cc.
320 #if !(defined(OS_MACOSX) && !defined(OS_IOS))
TEST(SharedMemoryTest,ShareReadOnly)321 TEST(SharedMemoryTest, ShareReadOnly) {
322   StringPiece contents = "Hello World";
323 
324   SharedMemory writable_shmem;
325   SharedMemoryCreateOptions options;
326   options.size = contents.size();
327   options.share_read_only = true;
328   ASSERT_TRUE(writable_shmem.Create(options));
329   ASSERT_TRUE(writable_shmem.Map(options.size));
330   memcpy(writable_shmem.memory(), contents.data(), contents.size());
331   EXPECT_TRUE(writable_shmem.Unmap());
332 
333   SharedMemoryHandle readonly_handle;
334   ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
335                                                     &readonly_handle));
336   SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
337 
338   ASSERT_TRUE(readonly_shmem.Map(contents.size()));
339   EXPECT_EQ(contents,
340             StringPiece(static_cast<const char*>(readonly_shmem.memory()),
341                         contents.size()));
342   EXPECT_TRUE(readonly_shmem.Unmap());
343 
344   // Make sure the writable instance is still writable.
345   ASSERT_TRUE(writable_shmem.Map(contents.size()));
346   StringPiece new_contents = "Goodbye";
347   memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
348   EXPECT_EQ(new_contents,
349             StringPiece(static_cast<const char*>(writable_shmem.memory()),
350                         new_contents.size()));
351 
352   // We'd like to check that if we send the read-only segment to another
353   // process, then that other process can't reopen it read/write.  (Since that
354   // would be a security hole.)  Setting up multiple processes is hard in a
355   // unittest, so this test checks that the *current* process can't reopen the
356   // segment read/write.  I think the test here is stronger than we actually
357   // care about, but there's a remote possibility that sending a file over a
358   // pipe would transform it into read/write.
359   SharedMemoryHandle handle = readonly_shmem.handle();
360 
361 #if defined(OS_ANDROID)
362   // The "read-only" handle is still writable on Android:
363   // http://crbug.com/320865
364   (void)handle;
365 #elif defined(OS_POSIX)
366   int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle);
367   EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE)
368       << "The descriptor itself should be read-only.";
369 
370   errno = 0;
371   void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE,
372                         MAP_SHARED, handle_fd, 0);
373   int mmap_errno = errno;
374   EXPECT_EQ(MAP_FAILED, writable)
375       << "It shouldn't be possible to re-mmap the descriptor writable.";
376   EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
377   if (writable != MAP_FAILED)
378     EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
379 
380 #elif defined(OS_WIN)
381   EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0))
382       << "Shouldn't be able to map memory writable.";
383 
384   HANDLE temp_handle;
385   BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
386                               GetCurrentProcess(), &temp_handle,
387                               FILE_MAP_ALL_ACCESS, false, 0);
388   EXPECT_EQ(FALSE, rv)
389       << "Shouldn't be able to duplicate the handle into a writable one.";
390   if (rv)
391     win::ScopedHandle writable_handle(temp_handle);
392   rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
393                          GetCurrentProcess(), &temp_handle, FILE_MAP_READ,
394                          false, 0);
395   EXPECT_EQ(TRUE, rv)
396       << "Should be able to duplicate the handle into a readable one.";
397   if (rv)
398     win::ScopedHandle writable_handle(temp_handle);
399 #else
400 #error Unexpected platform; write a test that tries to make 'handle' writable.
401 #endif  // defined(OS_POSIX) || defined(OS_WIN)
402 }
403 #endif  // !(defined(OS_MACOSX) && !defined(OS_IOS))
404 
TEST(SharedMemoryTest,ShareToSelf)405 TEST(SharedMemoryTest, ShareToSelf) {
406   StringPiece contents = "Hello World";
407 
408   SharedMemory shmem;
409   ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
410   memcpy(shmem.memory(), contents.data(), contents.size());
411   EXPECT_TRUE(shmem.Unmap());
412 
413   SharedMemoryHandle shared_handle;
414   ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
415 #if defined(OS_WIN)
416   ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
417 #endif
418   SharedMemory shared(shared_handle, /*readonly=*/false);
419 
420   ASSERT_TRUE(shared.Map(contents.size()));
421   EXPECT_EQ(
422       contents,
423       StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
424 
425   shared_handle = SharedMemoryHandle();
426   ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
427 #if defined(OS_WIN)
428   ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
429 #endif
430   SharedMemory readonly(shared_handle, /*readonly=*/true);
431 
432   ASSERT_TRUE(readonly.Map(contents.size()));
433   EXPECT_EQ(contents,
434             StringPiece(static_cast<const char*>(readonly.memory()),
435                         contents.size()));
436 }
437 
TEST(SharedMemoryTest,MapAt)438 TEST(SharedMemoryTest, MapAt) {
439   ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
440   const size_t kCount = SysInfo::VMAllocationGranularity();
441   const size_t kDataSize = kCount * sizeof(uint32_t);
442 
443   SharedMemory memory;
444   ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
445   uint32_t* ptr = static_cast<uint32_t*>(memory.memory());
446   ASSERT_NE(ptr, static_cast<void*>(NULL));
447 
448   for (size_t i = 0; i < kCount; ++i) {
449     ptr[i] = i;
450   }
451 
452   memory.Unmap();
453 
454   off_t offset = SysInfo::VMAllocationGranularity();
455   ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
456   offset /= sizeof(uint32_t);
457   ptr = static_cast<uint32_t*>(memory.memory());
458   ASSERT_NE(ptr, static_cast<void*>(NULL));
459   for (size_t i = offset; i < kCount; ++i) {
460     EXPECT_EQ(ptr[i - offset], i);
461   }
462 }
463 
TEST(SharedMemoryTest,MapTwice)464 TEST(SharedMemoryTest, MapTwice) {
465   const uint32_t kDataSize = 1024;
466   SharedMemory memory;
467   bool rv = memory.CreateAndMapAnonymous(kDataSize);
468   EXPECT_TRUE(rv);
469 
470   void* old_address = memory.memory();
471 
472   rv = memory.Map(kDataSize);
473   EXPECT_FALSE(rv);
474   EXPECT_EQ(old_address, memory.memory());
475 }
476 
477 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
478 // This test is not applicable for iOS (crbug.com/399384).
479 #if !defined(OS_IOS)
480 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
TEST(SharedMemoryTest,AnonymousExecutable)481 TEST(SharedMemoryTest, AnonymousExecutable) {
482   const uint32_t kTestSize = 1 << 16;
483 
484   SharedMemory shared_memory;
485   SharedMemoryCreateOptions options;
486   options.size = kTestSize;
487   options.executable = true;
488 
489   EXPECT_TRUE(shared_memory.Create(options));
490   EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
491 
492   EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
493                         PROT_READ | PROT_EXEC));
494 }
495 #endif  // !defined(OS_IOS)
496 
497 // Android supports a different permission model than POSIX for its "ashmem"
498 // shared memory implementation. So the tests about file permissions are not
499 // included on Android.
500 #if !defined(OS_ANDROID)
501 
502 // Set a umask and restore the old mask on destruction.
503 class ScopedUmaskSetter {
504  public:
ScopedUmaskSetter(mode_t target_mask)505   explicit ScopedUmaskSetter(mode_t target_mask) {
506     old_umask_ = umask(target_mask);
507   }
~ScopedUmaskSetter()508   ~ScopedUmaskSetter() { umask(old_umask_); }
509  private:
510   mode_t old_umask_;
511   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
512 };
513 
514 // Create a shared memory object, check its permissions.
TEST(SharedMemoryTest,FilePermissionsAnonymous)515 TEST(SharedMemoryTest, FilePermissionsAnonymous) {
516   const uint32_t kTestSize = 1 << 8;
517 
518   SharedMemory shared_memory;
519   SharedMemoryCreateOptions options;
520   options.size = kTestSize;
521   // Set a file mode creation mask that gives all permissions.
522   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
523 
524   EXPECT_TRUE(shared_memory.Create(options));
525 
526   int shm_fd =
527       SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
528   struct stat shm_stat;
529   EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
530   // Neither the group, nor others should be able to read the shared memory
531   // file.
532   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
533   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
534 }
535 
536 // Create a shared memory object, check its permissions.
TEST(SharedMemoryTest,FilePermissionsNamed)537 TEST(SharedMemoryTest, FilePermissionsNamed) {
538   const uint32_t kTestSize = 1 << 8;
539 
540   SharedMemory shared_memory;
541   SharedMemoryCreateOptions options;
542   options.size = kTestSize;
543 
544   // Set a file mode creation mask that gives all permissions.
545   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
546 
547   EXPECT_TRUE(shared_memory.Create(options));
548 
549   int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
550   struct stat shm_stat;
551   EXPECT_EQ(0, fstat(fd, &shm_stat));
552   // Neither the group, nor others should have been able to open the shared
553   // memory file while its name existed.
554   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
555   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
556 }
557 #endif  // !defined(OS_ANDROID)
558 
559 #endif  // defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
560 
561 // Map() will return addresses which are aligned to the platform page size, this
562 // varies from platform to platform though.  Since we'd like to advertise a
563 // minimum alignment that callers can count on, test for it here.
TEST(SharedMemoryTest,MapMinimumAlignment)564 TEST(SharedMemoryTest, MapMinimumAlignment) {
565   static const int kDataSize = 8192;
566 
567   SharedMemory shared_memory;
568   ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
569   EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
570       shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
571   shared_memory.Close();
572 }
573 
574 #if defined(OS_WIN)
TEST(SharedMemoryTest,UnsafeImageSection)575 TEST(SharedMemoryTest, UnsafeImageSection) {
576   const char kTestSectionName[] = "UnsafeImageSection";
577   wchar_t path[MAX_PATH];
578   EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
579 
580   // Map the current executable image to save us creating a new PE file on disk.
581   base::win::ScopedHandle file_handle(::CreateFile(
582       path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
583   EXPECT_TRUE(file_handle.IsValid());
584   base::win::ScopedHandle section_handle(
585       ::CreateFileMappingA(file_handle.Get(), nullptr,
586                            PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName));
587   EXPECT_TRUE(section_handle.IsValid());
588 
589   // Check direct opening by name, from handle and duplicated from handle.
590   SharedMemory shared_memory_open;
591   EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true));
592   EXPECT_FALSE(shared_memory_open.Map(1));
593   EXPECT_EQ(nullptr, shared_memory_open.memory());
594 
595   SharedMemory shared_memory_handle_local(
596       SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true);
597   EXPECT_FALSE(shared_memory_handle_local.Map(1));
598   EXPECT_EQ(nullptr, shared_memory_handle_local.memory());
599 
600   // Check that a handle without SECTION_QUERY also can't be mapped as it can't
601   // be checked.
602   SharedMemory shared_memory_handle_dummy;
603   SharedMemoryCreateOptions options;
604   options.size = 0x1000;
605   EXPECT_TRUE(shared_memory_handle_dummy.Create(options));
606   HANDLE handle_no_query;
607   EXPECT_TRUE(::DuplicateHandle(
608       ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(),
609       ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0));
610   SharedMemory shared_memory_handle_no_query(
611       SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true);
612   EXPECT_FALSE(shared_memory_handle_no_query.Map(1));
613   EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory());
614 }
615 #endif  // defined(OS_WIN)
616 
617 // iOS does not allow multiple processes.
618 // Android ashmem does not support named shared memory.
619 // Mac SharedMemory does not support named shared memory. crbug.com/345734
620 #if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
621 // On POSIX it is especially important we test shmem across processes,
622 // not just across threads.  But the test is enabled on all platforms.
623 class SharedMemoryProcessTest : public MultiProcessTest {
624  public:
CleanUp()625   static void CleanUp() {
626     SharedMemory memory;
627     memory.Delete(s_test_name_);
628   }
629 
TaskTestMain()630   static int TaskTestMain() {
631     int errors = 0;
632     SharedMemory memory;
633     bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
634     EXPECT_TRUE(rv);
635     if (rv != true)
636       errors++;
637     rv = memory.Map(s_data_size_);
638     EXPECT_TRUE(rv);
639     if (rv != true)
640       errors++;
641     int* ptr = static_cast<int*>(memory.memory());
642 
643     // This runs concurrently in multiple processes. Writes need to be atomic.
644     subtle::Barrier_AtomicIncrement(ptr, 1);
645     memory.Close();
646     return errors;
647   }
648 
649   static const char s_test_name_[];
650   static const uint32_t s_data_size_;
651 };
652 
653 const char SharedMemoryProcessTest::s_test_name_[] = "MPMem";
654 const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024;
655 
TEST_F(SharedMemoryProcessTest,SharedMemoryAcrossProcesses)656 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
657   const int kNumTasks = 5;
658 
659   SharedMemoryProcessTest::CleanUp();
660 
661   // Create a shared memory region. Set the first word to 0.
662   SharedMemory memory;
663   bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
664   ASSERT_TRUE(rv);
665   rv = memory.Map(s_data_size_);
666   ASSERT_TRUE(rv);
667   int* ptr = static_cast<int*>(memory.memory());
668   *ptr = 0;
669 
670   // Start |kNumTasks| processes, each of which atomically increments the first
671   // word by 1.
672   Process processes[kNumTasks];
673   for (int index = 0; index < kNumTasks; ++index) {
674     processes[index] = SpawnChild("SharedMemoryTestMain");
675     ASSERT_TRUE(processes[index].IsValid());
676   }
677 
678   // Check that each process exited correctly.
679   int exit_code = 0;
680   for (int index = 0; index < kNumTasks; ++index) {
681     EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
682     EXPECT_EQ(0, exit_code);
683   }
684 
685   // Check that the shared memory region reflects |kNumTasks| increments.
686   ASSERT_EQ(kNumTasks, *ptr);
687 
688   memory.Close();
689   SharedMemoryProcessTest::CleanUp();
690 }
691 
MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain)692 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
693   return SharedMemoryProcessTest::TaskTestMain();
694 }
695 #endif  // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
696 
697 }  // namespace base
698