| Index: base/memory/shared_memory_unittest.cc
|
| diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
|
| index 892fd7f1a590b0d20b8f9e6289b07a225c8676fa..93b8d839ba0992eb225b150403c7c1aa12d2f1c2 100644
|
| --- a/base/memory/shared_memory_unittest.cc
|
| +++ b/base/memory/shared_memory_unittest.cc
|
| @@ -20,12 +20,18 @@
|
| #endif
|
|
|
| #if defined(OS_POSIX)
|
| +#include <errno.h>
|
| +#include <fcntl.h>
|
| #include <sys/mman.h>
|
| #include <sys/stat.h>
|
| #include <sys/types.h>
|
| #include <unistd.h>
|
| #endif
|
|
|
| +#if defined(OS_WIN)
|
| +#include "base/win/scoped_handle.h"
|
| +#endif
|
| +
|
| static const int kNumThreads = 5;
|
| static const int kNumTasks = 5;
|
|
|
| @@ -361,6 +367,69 @@ TEST(SharedMemoryTest, AnonymousPrivate) {
|
| }
|
| }
|
|
|
| +TEST(SharedMemoryTest, ShareReadOnly) {
|
| + StringPiece contents = "Hello World";
|
| +
|
| + SharedMemory writable_shmem;
|
| + ASSERT_TRUE(writable_shmem.CreateAndMapAnonymous(contents.size()));
|
| + memcpy(writable_shmem.memory(), contents.data(), contents.size());
|
| +
|
| + SharedMemoryHandle readonly_handle;
|
| + ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
|
| + &readonly_handle));
|
| + SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
|
| +
|
| + ASSERT_TRUE(readonly_shmem.Map(contents.size()));
|
| + EXPECT_EQ(contents,
|
| + StringPiece(static_cast<const char*>(readonly_shmem.memory()),
|
| + contents.size()));
|
| +
|
| + // We'd like to check that if we send the read-only segment to another
|
| + // process, then that other process can't reopen it read/write. (Since that
|
| + // would be a security hole.) Setting up multiple processes is hard in a
|
| + // unittest, so this test checks that the *current* process can't reopen the
|
| + // segment read/write. I think the test here is stronger than we actually
|
| + // care about, but there's a remote possibility that sending a file over a
|
| + // pipe would transform it into read/write.
|
| + SharedMemoryHandle handle = readonly_shmem.handle();
|
| +
|
| +#if defined(OS_POSIX)
|
| + EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE)
|
| + << "The descriptor itself should be read-only.";
|
| +
|
| + errno = 0;
|
| + void* writable = mmap(NULL,
|
| + readonly_shmem.mapped_size(),
|
| + PROT_READ | PROT_WRITE,
|
| + MAP_SHARED,
|
| + handle.fd,
|
| + 0);
|
| + int mmap_errno = errno;
|
| + EXPECT_EQ(MAP_FAILED, writable)
|
| + << "It shouldn't be possible to re-mmap the descriptor writable.";
|
| + EXPECT_EQ(EACCES, mmap_errno);
|
| + if (writable != MAP_FAILED)
|
| + EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
|
| +
|
| +#elif defined(OS_WIN)
|
| + EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0))
|
| + << "Shouldn't be able to map memory writable.";
|
| +
|
| + base::win::ScopedHandle writable_handle;
|
| + EXPECT_EQ(0,
|
| + ::DuplicateHandle(GetCurrentProcess(),
|
| + handle,
|
| + GetCurrentProcess,
|
| + writable_handle.Receive(),
|
| + FILE_MAP_ALL_ACCESS,
|
| + false,
|
| + 0))
|
| + << "Shouldn't be able to duplicate the handle into a writable one.";
|
| +#else
|
| +#error Unexpected platform; write a test that tries to make 'handle' writable.
|
| +#endif // defined(OS_POSIX) || defined(OS_WIN)
|
| +}
|
| +
|
| TEST(SharedMemoryTest, MapAt) {
|
| ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32));
|
| const size_t kCount = SysInfo::VMAllocationGranularity();
|
|
|