| Index: ipc/attachment_broker_privileged_mac_unittest.cc
|
| diff --git a/ipc/attachment_broker_privileged_mac_unittest.cc b/ipc/attachment_broker_privileged_mac_unittest.cc
|
| deleted file mode 100644
|
| index 330db03af9618d2842b90ed7b5ef1b11d64f8a80..0000000000000000000000000000000000000000
|
| --- a/ipc/attachment_broker_privileged_mac_unittest.cc
|
| +++ /dev/null
|
| @@ -1,428 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "ipc/attachment_broker_privileged_mac.h"
|
| -
|
| -#include <mach/mach.h>
|
| -#include <mach/mach_vm.h>
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <map>
|
| -#include <memory>
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/mac/mac_util.h"
|
| -#include "base/mac/mach_logging.h"
|
| -#include "base/mac/mach_port_util.h"
|
| -#include "base/mac/scoped_mach_port.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/shared_memory.h"
|
| -#include "base/process/port_provider_mac.h"
|
| -#include "base/process/process_handle.h"
|
| -#include "base/sys_info.h"
|
| -#include "base/test/multiprocess_test.h"
|
| -#include "base/test/test_timeouts.h"
|
| -#include "ipc/test_util_mac.h"
|
| -#include "testing/multiprocess_func_list.h"
|
| -
|
| -namespace IPC {
|
| -
|
| -namespace {
|
| -
|
| -static const std::string g_service_switch_name = "service_name";
|
| -
|
| -// Sends a uint32_t to a mach port.
|
| -void SendUInt32(mach_port_t port, uint32_t message) {
|
| - int message_size = sizeof(uint32_t);
|
| - int total_size = message_size + sizeof(mach_msg_header_t);
|
| - void* buffer = malloc(total_size);
|
| - mach_msg_header_t* header = (mach_msg_header_t*)buffer;
|
| - header->msgh_remote_port = port;
|
| - header->msgh_local_port = MACH_PORT_NULL;
|
| - header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
|
| - header->msgh_reserved = 0;
|
| - header->msgh_id = 0;
|
| - header->msgh_size = total_size;
|
| - memcpy(static_cast<char*>(buffer) + sizeof(mach_msg_header_t), &message,
|
| - message_size);
|
| -
|
| - kern_return_t kr;
|
| - kr = mach_msg(static_cast<mach_msg_header_t*>(buffer), MACH_SEND_MSG,
|
| - total_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
|
| - MACH_PORT_NULL);
|
| - MACH_CHECK(kr == KERN_SUCCESS, kr) << "SendUInt32";
|
| - free(buffer);
|
| -}
|
| -
|
| -// Receives a uint32_t from a mach port.
|
| -uint32_t ReceiveUInt32(mach_port_t listening_port) {
|
| - int message_size = sizeof(uint32_t);
|
| - int total_size =
|
| - message_size + sizeof(mach_msg_header_t) + sizeof(mach_msg_trailer_t);
|
| - int options = MACH_RCV_MSG;
|
| - void* buffer = malloc(total_size);
|
| -
|
| - int kr =
|
| - mach_msg(static_cast<mach_msg_header_t*>(buffer), options, 0, total_size,
|
| - listening_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
| - MACH_CHECK(kr == KERN_SUCCESS, kr) << "ReceiveUInt32";
|
| -
|
| - uint32_t response;
|
| - memcpy(&response, static_cast<char*>(buffer) + sizeof(mach_msg_header_t),
|
| - message_size);
|
| -
|
| - free(buffer);
|
| - return response;
|
| -}
|
| -
|
| -// Sets up the mach communication ports with the server. Returns a port to which
|
| -// the server will send mach objects.
|
| -// |original_name_count| is an output variable that describes the number of
|
| -// active names in this task before the task port is shared with the server.
|
| -base::mac::ScopedMachReceiveRight CommonChildProcessSetUp(
|
| - mach_msg_type_number_t* original_name_count) {
|
| - base::CommandLine cmd_line = *base::CommandLine::ForCurrentProcess();
|
| - std::string service_name =
|
| - cmd_line.GetSwitchValueASCII(g_service_switch_name);
|
| - base::mac::ScopedMachSendRight server_port(
|
| - LookupServer(service_name.c_str()));
|
| - base::mac::ScopedMachReceiveRight client_port(MakeReceivingPort());
|
| -
|
| - // |server_port| is a newly allocated right which will be deallocated once
|
| - // this method returns.
|
| - *original_name_count = GetActiveNameCount() - 1;
|
| -
|
| - // Send the port that this process is listening on to the server.
|
| - SendMachPort(server_port.get(), client_port.get(), MACH_MSG_TYPE_MAKE_SEND);
|
| -
|
| - // Send the task port for this process.
|
| - SendMachPort(server_port.get(), mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
|
| - return client_port;
|
| -}
|
| -
|
| -// Creates a new shared memory region populated with 'a'.
|
| -std::unique_ptr<base::SharedMemory> CreateAndPopulateSharedMemoryHandle(
|
| - size_t size) {
|
| - base::SharedMemoryHandle shm(size);
|
| - std::unique_ptr<base::SharedMemory> shared_memory(
|
| - new base::SharedMemory(shm, false));
|
| - shared_memory->Map(size);
|
| - memset(shared_memory->memory(), 'a', size);
|
| - return shared_memory;
|
| -}
|
| -
|
| -// Create a shared memory region from a memory object. The returned object takes
|
| -// ownership of |memory_object|.
|
| -std::unique_ptr<base::SharedMemory> MapMemoryObject(mach_port_t memory_object,
|
| - size_t size) {
|
| - base::SharedMemoryHandle shm(memory_object, size, base::GetCurrentProcId());
|
| - std::unique_ptr<base::SharedMemory> shared_memory(
|
| - new base::SharedMemory(shm, false));
|
| - shared_memory->Map(size);
|
| - return shared_memory;
|
| -}
|
| -
|
| -class MockPortProvider : public base::PortProvider {
|
| - public:
|
| - MockPortProvider() {}
|
| - ~MockPortProvider() override {}
|
| - mach_port_t TaskForPid(base::ProcessHandle process) const override {
|
| - return MACH_PORT_NULL;
|
| - }
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -class AttachmentBrokerPrivilegedMacMultiProcessTest
|
| - : public base::MultiProcessTest {
|
| - public:
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest() {}
|
| -
|
| - base::CommandLine MakeCmdLine(const std::string& procname) override {
|
| - base::CommandLine command_line = MultiProcessTest::MakeCmdLine(procname);
|
| - // Pass the service name to the child process.
|
| - command_line.AppendSwitchASCII(g_service_switch_name, service_name_);
|
| - return command_line;
|
| - }
|
| -
|
| - void SetUpChild(const std::string& name) {
|
| - // Make a random service name so that this test doesn't conflict with other
|
| - // similar tests.
|
| - service_name_ = CreateRandomServiceName();
|
| - server_port_.reset(BecomeMachServer(service_name_.c_str()).release());
|
| - child_process_ = SpawnChild(name);
|
| - client_port_.reset(ReceiveMachPort(server_port_.get()).release());
|
| - client_task_port_.reset(ReceiveMachPort(server_port_.get()).release());
|
| - }
|
| -
|
| - static const int s_memory_size = 99999;
|
| -
|
| - protected:
|
| - std::string service_name_;
|
| -
|
| - // A port on which the main process listens for mach messages from the child
|
| - // process.
|
| - base::mac::ScopedMachReceiveRight server_port_;
|
| -
|
| - // A port on which the child process listens for mach messages from the main
|
| - // process.
|
| - base::mac::ScopedMachSendRight client_port_;
|
| -
|
| - // Child process's task port.
|
| - base::mac::ScopedMachSendRight client_task_port_;
|
| -
|
| - // Dummy port provider.
|
| - MockPortProvider port_provider_;
|
| -
|
| - base::Process child_process_;
|
| - DISALLOW_COPY_AND_ASSIGN(AttachmentBrokerPrivilegedMacMultiProcessTest);
|
| -};
|
| -
|
| -// The attachment broker inserts a right for a memory object into the
|
| -// destination task.
|
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertRight) {
|
| - SetUpChild("InsertRightClient");
|
| - mach_msg_type_number_t original_name_count = GetActiveNameCount();
|
| - IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
|
| -
|
| - // Create some shared memory.
|
| - std::unique_ptr<base::SharedMemory> shared_memory =
|
| - CreateAndPopulateSharedMemoryHandle(s_memory_size);
|
| - ASSERT_TRUE(shared_memory->handle().IsValid());
|
| -
|
| - // Insert the memory object into the destination task, via an intermediate
|
| - // port.
|
| - IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
|
| - MACH_PORT_RIGHT_SEND);
|
| - mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
|
| - client_task_port_.get(),
|
| - base::mac::ScopedMachSendRight(shared_memory->handle().GetMemoryObject()),
|
| - nullptr);
|
| - EXPECT_NE(inserted_memory_object,
|
| - static_cast<mach_port_name_t>(MACH_PORT_NULL));
|
| - SendUInt32(client_port_.get(), inserted_memory_object);
|
| -
|
| - // Check that no names have been leaked.
|
| - shared_memory.reset();
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - int rv = -1;
|
| - ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
|
| - TestTimeouts::action_timeout(), &rv));
|
| - EXPECT_EQ(0, rv);
|
| -}
|
| -
|
| -MULTIPROCESS_TEST_MAIN(InsertRightClient) {
|
| - mach_msg_type_number_t original_name_count = 0;
|
| - base::mac::ScopedMachReceiveRight client_port(
|
| - CommonChildProcessSetUp(&original_name_count).release());
|
| - base::mac::ScopedMachReceiveRight inserted_port(
|
| - ReceiveUInt32(client_port.get()));
|
| - base::mac::ScopedMachSendRight memory_object(
|
| - ReceiveMachPort(inserted_port.get()));
|
| - inserted_port.reset();
|
| -
|
| - // The server should have inserted a right into this process.
|
| - EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
|
| -
|
| - // Map the memory object and check its contents.
|
| - std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
|
| - memory_object.release(),
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
|
| - const char* start = static_cast<const char*>(shared_memory->memory());
|
| - for (int i = 0;
|
| - i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
|
| - DCHECK_EQ(start[i], 'a');
|
| - }
|
| -
|
| - // Check that no names have been leaked.
|
| - shared_memory.reset();
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// The attachment broker inserts the right for a memory object into the
|
| -// destination task twice.
|
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertSameRightTwice) {
|
| - SetUpChild("InsertSameRightTwiceClient");
|
| - mach_msg_type_number_t original_name_count = GetActiveNameCount();
|
| - IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
|
| -
|
| - // Create some shared memory.
|
| - std::unique_ptr<base::SharedMemory> shared_memory =
|
| - CreateAndPopulateSharedMemoryHandle(s_memory_size);
|
| - ASSERT_TRUE(shared_memory->handle().IsValid());
|
| -
|
| - // Insert the memory object into the destination task, via an intermediate
|
| - // port, twice.
|
| - for (int i = 0; i < 2; ++i) {
|
| - IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
|
| - MACH_PORT_RIGHT_SEND);
|
| - mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
|
| - client_task_port_.get(),
|
| - base::mac::ScopedMachSendRight(
|
| - shared_memory->handle().GetMemoryObject()),
|
| - nullptr);
|
| - EXPECT_NE(inserted_memory_object,
|
| - static_cast<mach_port_name_t>(MACH_PORT_NULL));
|
| - SendUInt32(client_port_.get(), inserted_memory_object);
|
| - }
|
| -
|
| - // Check that no names have been leaked.
|
| - shared_memory.reset();
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - int rv = -1;
|
| - ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
|
| - TestTimeouts::action_timeout(), &rv));
|
| - EXPECT_EQ(0, rv);
|
| -}
|
| -
|
| -MULTIPROCESS_TEST_MAIN(InsertSameRightTwiceClient) {
|
| - mach_msg_type_number_t original_name_count = 0;
|
| - base::mac::ScopedMachReceiveRight client_port(
|
| - CommonChildProcessSetUp(&original_name_count).release());
|
| -
|
| - // Receive two memory objects.
|
| - base::mac::ScopedMachReceiveRight inserted_port(
|
| - ReceiveUInt32(client_port.get()));
|
| - base::mac::ScopedMachReceiveRight inserted_port2(
|
| - ReceiveUInt32(client_port.get()));
|
| - base::mac::ScopedMachSendRight memory_object(
|
| - ReceiveMachPort(inserted_port.get()));
|
| - base::mac::ScopedMachSendRight memory_object2(
|
| - ReceiveMachPort(inserted_port2.get()));
|
| - inserted_port.reset();
|
| - inserted_port2.reset();
|
| -
|
| - // Both rights are for the same Mach port, so only one new name should appear.
|
| - EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
|
| -
|
| - // Map both memory objects and check their contents.
|
| - std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
|
| - memory_object.release(),
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
|
| - char* start = static_cast<char*>(shared_memory->memory());
|
| - for (int i = 0;
|
| - i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
|
| - DCHECK_EQ(start[i], 'a');
|
| - }
|
| -
|
| - std::unique_ptr<base::SharedMemory> shared_memory2(MapMemoryObject(
|
| - memory_object2.release(),
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
|
| - char* start2 = static_cast<char*>(shared_memory2->memory());
|
| - for (int i = 0;
|
| - i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
|
| - DCHECK_EQ(start2[i], 'a');
|
| - }
|
| -
|
| - // Check that the contents of both regions are shared.
|
| - start[0] = 'b';
|
| - DCHECK_EQ(start2[0], 'b');
|
| -
|
| - // After releasing one shared memory region, the name count shouldn't change,
|
| - // since another reference exists.
|
| - shared_memory.reset();
|
| - EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
|
| -
|
| - // After releasing the second shared memory region, the name count should be
|
| - // as if no names were ever inserted
|
| - shared_memory2.reset();
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// The attachment broker inserts the rights for two memory objects into the
|
| -// destination task.
|
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertTwoRights) {
|
| - SetUpChild("InsertTwoRightsClient");
|
| - mach_msg_type_number_t original_name_count = GetActiveNameCount();
|
| - IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
|
| -
|
| - for (int i = 0; i < 2; ++i) {
|
| - // Create some shared memory.
|
| - std::unique_ptr<base::SharedMemory> shared_memory =
|
| - CreateAndPopulateSharedMemoryHandle(s_memory_size);
|
| - ASSERT_TRUE(shared_memory->handle().IsValid());
|
| -
|
| - // Insert the memory object into the destination task, via an intermediate
|
| - // port.
|
| - IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
|
| - MACH_PORT_RIGHT_SEND);
|
| - mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
|
| - client_task_port_.get(),
|
| - base::mac::ScopedMachSendRight(
|
| - shared_memory->handle().GetMemoryObject()),
|
| - nullptr);
|
| - EXPECT_NE(inserted_memory_object,
|
| - static_cast<mach_port_name_t>(MACH_PORT_NULL));
|
| - SendUInt32(client_port_.get(), inserted_memory_object);
|
| - }
|
| -
|
| - // Check that no names have been leaked.
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - int rv = -1;
|
| - ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
|
| - TestTimeouts::action_timeout(), &rv));
|
| - EXPECT_EQ(0, rv);
|
| -}
|
| -
|
| -MULTIPROCESS_TEST_MAIN(InsertTwoRightsClient) {
|
| - mach_msg_type_number_t original_name_count = 0;
|
| - base::mac::ScopedMachReceiveRight client_port(
|
| - CommonChildProcessSetUp(&original_name_count).release());
|
| -
|
| - // Receive two memory objects.
|
| - base::mac::ScopedMachReceiveRight inserted_port(
|
| - ReceiveUInt32(client_port.get()));
|
| - base::mac::ScopedMachReceiveRight inserted_port2(
|
| - ReceiveUInt32(client_port.get()));
|
| - base::mac::ScopedMachSendRight memory_object(
|
| - ReceiveMachPort(inserted_port.get()));
|
| - base::mac::ScopedMachSendRight memory_object2(
|
| - ReceiveMachPort(inserted_port2.get()));
|
| - inserted_port.reset();
|
| - inserted_port2.reset();
|
| -
|
| - // There should be two new names to reflect the two new shared memory regions.
|
| - EXPECT_EQ(original_name_count + 2, GetActiveNameCount());
|
| -
|
| - // Map both memory objects and check their contents.
|
| - std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
|
| - memory_object.release(),
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
|
| - char* start = static_cast<char*>(shared_memory->memory());
|
| - for (int i = 0;
|
| - i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
|
| - DCHECK_EQ(start[i], 'a');
|
| - }
|
| -
|
| - std::unique_ptr<base::SharedMemory> shared_memory2(MapMemoryObject(
|
| - memory_object2.release(),
|
| - AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
|
| - char* start2 = static_cast<char*>(shared_memory2->memory());
|
| - for (int i = 0;
|
| - i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
|
| - DCHECK_EQ(start2[i], 'a');
|
| - }
|
| -
|
| - // Check that the contents of both regions are not shared.
|
| - start[0] = 'b';
|
| - DCHECK_EQ(start2[0], 'a');
|
| -
|
| - // After releasing one shared memory region, the name count should decrement.
|
| - shared_memory.reset();
|
| - EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
|
| - shared_memory2.reset();
|
| - EXPECT_EQ(original_name_count, GetActiveNameCount());
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -} // namespace IPC
|
|
|