diff options
author | erikchen <erikchen@chromium.org> | 2015-08-11 14:17:47 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-11 21:18:44 +0000 |
commit | 959039d06c1677f2d90fc7d84cb9ad9d310842bd (patch) | |
tree | bf326c766e7d0b040bcbcf0110f73d3b7d0ddd5a /ipc | |
parent | 1d30631db4ff58e63c4ae4b7132cb136fb0c37b3 (diff) | |
download | chromium_src-959039d06c1677f2d90fc7d84cb9ad9d310842bd.zip chromium_src-959039d06c1677f2d90fc7d84cb9ad9d310842bd.tar.gz chromium_src-959039d06c1677f2d90fc7d84cb9ad9d310842bd.tar.bz2 |
ipc: Add the class HandleWin.
HandleWin is a wrapper around a Windows HANDLE that can be transported across
IPC channels that support attachment brokering. The attachment broker is
responsible for duplicating the HANDLE into the destination process.
BUG=493414
Review URL: https://codereview.chromium.org/1281083004
Cr-Commit-Position: refs/heads/master@{#342897}
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/BUILD.gn | 2 | ||||
-rw-r--r-- | ipc/attachment_broker_messages.h | 4 | ||||
-rw-r--r-- | ipc/attachment_broker_privileged_win.cc | 23 | ||||
-rw-r--r-- | ipc/attachment_broker_privileged_win.h | 2 | ||||
-rw-r--r-- | ipc/attachment_broker_privileged_win_unittest.cc | 31 | ||||
-rw-r--r-- | ipc/attachment_broker_unprivileged_win_unittest.cc | 4 | ||||
-rw-r--r-- | ipc/handle_attachment_win.cc | 14 | ||||
-rw-r--r-- | ipc/handle_attachment_win.h | 6 | ||||
-rw-r--r-- | ipc/handle_win.cc | 53 | ||||
-rw-r--r-- | ipc/handle_win.h | 52 | ||||
-rw-r--r-- | ipc/ipc.gypi | 2 |
11 files changed, 179 insertions, 14 deletions
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn index eb59274..2fe70bb 100644 --- a/ipc/BUILD.gn +++ b/ipc/BUILD.gn @@ -21,6 +21,8 @@ component("ipc") { "brokerable_attachment.h", "handle_attachment_win.cc", "handle_attachment_win.h", + "handle_win.cc", + "handle_win.h", "ipc_channel.cc", "ipc_channel.h", "ipc_channel_common.cc", diff --git a/ipc/attachment_broker_messages.h b/ipc/attachment_broker_messages.h index 066e19c..f0e103d 100644 --- a/ipc/attachment_broker_messages.h +++ b/ipc/attachment_broker_messages.h @@ -19,9 +19,13 @@ // ---------------------------------------------------------------------------- #if defined(OS_WIN) +// Define the serialization for Permissions. +IPC_ENUM_TRAITS_MAX_VALUE(HandleWin::Permissions, HandleWin::MAX_PERMISSIONS); + IPC_STRUCT_TRAITS_BEGIN(IPC::internal::HandleAttachmentWin::WireFormat) IPC_STRUCT_TRAITS_MEMBER(handle) IPC_STRUCT_TRAITS_MEMBER(destination_process) + IPC_STRUCT_TRAITS_MEMBER(permissions) IPC_STRUCT_TRAITS_MEMBER(attachment_id) IPC_STRUCT_TRAITS_END() #endif // defined(OS_WIN) diff --git a/ipc/attachment_broker_privileged_win.cc b/ipc/attachment_broker_privileged_win.cc index 77584cf..c8cc1d0 100644 --- a/ipc/attachment_broker_privileged_win.cc +++ b/ipc/attachment_broker_privileged_win.cc @@ -95,6 +95,8 @@ AttachmentBrokerPrivilegedWin::DuplicateWinHandle( HandleWireFormat new_wire_format; new_wire_format.destination_process = wire_format.destination_process; new_wire_format.attachment_id = wire_format.attachment_id; + new_wire_format.permissions = wire_format.permissions; + new_wire_format.handle = 0; HANDLE original_handle = LongToHandle(wire_format.handle); @@ -103,15 +105,28 @@ AttachmentBrokerPrivilegedWin::DuplicateWinHandle( base::Process dest_process = base::Process::OpenWithExtraPrivileges(wire_format.destination_process); if (source_process.Handle() && dest_process.Handle()) { + DWORD desired_access = 0; + DWORD options = 0; + switch (wire_format.permissions) { + case HandleWin::INVALID: + LOG(ERROR) << "Received invalid permissions for duplication."; + return new_wire_format; + case HandleWin::DUPLICATE: + options = DUPLICATE_SAME_ACCESS; + break; + case HandleWin::FILE_READ_WRITE: + desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; + break; + } + HANDLE new_handle; DWORD result = ::DuplicateHandle(source_process.Handle(), original_handle, - dest_process.Handle(), &new_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); + dest_process.Handle(), &new_handle, + desired_access, FALSE, options); new_wire_format.handle = (result != 0) ? HandleToLong(new_handle) : 0; - } else { - new_wire_format.handle = 0; } + return new_wire_format; } diff --git a/ipc/attachment_broker_privileged_win.h b/ipc/attachment_broker_privileged_win.h index dca05f5..67104b8 100644 --- a/ipc/attachment_broker_privileged_win.h +++ b/ipc/attachment_broker_privileged_win.h @@ -29,7 +29,7 @@ class IPC_EXPORT AttachmentBrokerPrivilegedWin private: using HandleWireFormat = internal::HandleAttachmentWin::WireFormat; // IPC message handlers. - void OnDuplicateWinHandle(const IPC::Message& message); + void OnDuplicateWinHandle(const Message& message); // Duplicates |wire_Format| from |source_process| into its destination // process. diff --git a/ipc/attachment_broker_privileged_win_unittest.cc b/ipc/attachment_broker_privileged_win_unittest.cc index 3df4006..6e8f881 100644 --- a/ipc/attachment_broker_privileged_win_unittest.cc +++ b/ipc/attachment_broker_privileged_win_unittest.cc @@ -13,6 +13,7 @@ #include "ipc/attachment_broker_privileged_win.h" #include "ipc/attachment_broker_unprivileged_win.h" #include "ipc/handle_attachment_win.h" +#include "ipc/handle_win.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" #include "ipc/ipc_test_base.h" @@ -191,7 +192,7 @@ class IPCAttachmentBrokerPrivilegedWinTest : public IPCTestBase { new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); message->WriteInt(message_index_++); scoped_refptr<IPC::internal::HandleAttachmentWin> attachment( - new IPC::internal::HandleAttachmentWin(h)); + new IPC::internal::HandleAttachmentWin(h, IPC::HandleWin::DUPLICATE)); ASSERT_TRUE(message->WriteAttachment(attachment)); sender()->Send(message); } @@ -305,6 +306,30 @@ TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleToSelf) { CommonTearDown(); } +// Similar to SendHandle, except this test uses the HandleWin class. +TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleWin) { + Init("SendHandleWin"); + + CommonSetUp(); + ResultListener result_listener; + get_proxy_listener()->set_listener(&result_listener); + + HANDLE h = CreateTempFile(); + IPC::HandleWin handle_win(h, IPC::HandleWin::FILE_READ_WRITE); + IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); + message->WriteInt(0); + IPC::ParamTraits<IPC::HandleWin>::Write(message, handle_win); + sender()->Send(message); + base::MessageLoop::current()->Run(); + + // Check the result. + ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, + get_proxy_listener()->get_reason()); + ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); + + CommonTearDown(); +} + using OnMessageReceivedCallback = void (*)(MockObserver* observer, IPC::AttachmentBrokerPrivilegedWin* broker, @@ -399,4 +424,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleToSelf) { "SendHandleToSelf"); } +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleWin) { + return CommonPrivilegedProcessMain(&SendHandleCallback, "SendHandleWin"); +} + } // namespace diff --git a/ipc/attachment_broker_unprivileged_win_unittest.cc b/ipc/attachment_broker_unprivileged_win_unittest.cc index c260997..e67c54a 100644 --- a/ipc/attachment_broker_unprivileged_win_unittest.cc +++ b/ipc/attachment_broker_unprivileged_win_unittest.cc @@ -20,7 +20,7 @@ TEST(AttachmentBrokerUnprivilegedWinTest, ReceiveValidMessage) { HANDLE handle = LongToHandle(8); base::ProcessId destination = base::Process::Current().Pid(); scoped_refptr<internal::HandleAttachmentWin> attachment( - new internal::HandleAttachmentWin(handle)); + new internal::HandleAttachmentWin(handle, HandleWin::DUPLICATE)); AttachmentBrokerMsg_WinHandleHasBeenDuplicated msg( attachment->GetWireFormat(destination)); AttachmentBrokerUnprivilegedWin attachment_broker; @@ -40,7 +40,7 @@ TEST(AttachmentBrokerUnprivilegedWinTest, ReceiveInvalidMessage) { HANDLE handle = LongToHandle(8); base::ProcessId destination = base::Process::Current().Pid() + 1; scoped_refptr<internal::HandleAttachmentWin> attachment( - new internal::HandleAttachmentWin(handle)); + new internal::HandleAttachmentWin(handle, HandleWin::DUPLICATE)); AttachmentBrokerMsg_WinHandleHasBeenDuplicated msg( attachment->GetWireFormat(destination)); AttachmentBrokerUnprivilegedWin attachment_broker; diff --git a/ipc/handle_attachment_win.cc b/ipc/handle_attachment_win.cc index 994b22d..50e3e6d 100644 --- a/ipc/handle_attachment_win.cc +++ b/ipc/handle_attachment_win.cc @@ -9,17 +9,20 @@ namespace IPC { namespace internal { -HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle) - : handle_(handle) { -} +HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle, + HandleWin::Permissions permissions) + : handle_(handle), permissions_(permissions) {} HandleAttachmentWin::HandleAttachmentWin(const WireFormat& wire_format) : BrokerableAttachment(wire_format.attachment_id, false), - handle_(LongToHandle(wire_format.handle)) {} + handle_(LongToHandle(wire_format.handle)), + permissions_(wire_format.permissions) {} HandleAttachmentWin::HandleAttachmentWin( const BrokerableAttachment::AttachmentId& id) - : BrokerableAttachment(id, true), handle_(INVALID_HANDLE_VALUE) {} + : BrokerableAttachment(id, true), + handle_(INVALID_HANDLE_VALUE), + permissions_(HandleWin::INVALID) {} HandleAttachmentWin::~HandleAttachmentWin() { } @@ -48,6 +51,7 @@ HandleAttachmentWin::WireFormat HandleAttachmentWin::GetWireFormat( format.handle = HandleToLong(handle_); format.attachment_id = GetIdentifier(); format.destination_process = destination; + format.permissions = permissions_; return format; } diff --git a/ipc/handle_attachment_win.h b/ipc/handle_attachment_win.h index e164cc0..127cd57 100644 --- a/ipc/handle_attachment_win.h +++ b/ipc/handle_attachment_win.h @@ -9,6 +9,7 @@ #include "base/process/process_handle.h" #include "ipc/brokerable_attachment.h" +#include "ipc/handle_win.h" #include "ipc/ipc_export.h" namespace IPC { @@ -29,10 +30,12 @@ class IPC_EXPORT HandleAttachmentWin : public BrokerableAttachment { int32_t handle; // The id of the destination process that the handle is duplicated into. base::ProcessId destination_process; + // The permissions to use when duplicating the handle. + HandleWin::Permissions permissions; AttachmentId attachment_id; }; - explicit HandleAttachmentWin(const HANDLE& handle); + HandleAttachmentWin(const HANDLE& handle, HandleWin::Permissions permissions); explicit HandleAttachmentWin(const WireFormat& wire_format); explicit HandleAttachmentWin(const BrokerableAttachment::AttachmentId& id); @@ -47,6 +50,7 @@ class IPC_EXPORT HandleAttachmentWin : public BrokerableAttachment { private: ~HandleAttachmentWin() override; HANDLE handle_; + HandleWin::Permissions permissions_; }; } // namespace internal diff --git a/ipc/handle_win.cc b/ipc/handle_win.cc new file mode 100644 index 0000000..ea268bd --- /dev/null +++ b/ipc/handle_win.cc @@ -0,0 +1,53 @@ +// 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/handle_win.h" + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/strings/string_number_conversions.h" +#include "ipc/handle_attachment_win.h" + +namespace IPC { + +HandleWin::HandleWin(const HANDLE& handle, Permissions permissions) + : handle_(handle), permissions_(permissions) {} + +// static +void ParamTraits<HandleWin>::Write(Message* m, const param_type& p) { + scoped_refptr<IPC::internal::HandleAttachmentWin> attachment( + new IPC::internal::HandleAttachmentWin(p.get_handle(), + p.get_permissions())); + if (!m->WriteAttachment(attachment.Pass())) + NOTREACHED(); +} + +// static +bool ParamTraits<HandleWin>::Read(const Message* m, + base::PickleIterator* iter, + param_type* r) { + scoped_refptr<MessageAttachment> attachment; + if (!m->ReadAttachment(iter, &attachment)) + return false; + if (attachment->GetType() != MessageAttachment::TYPE_BROKERABLE_ATTACHMENT) + return false; + BrokerableAttachment* brokerable_attachment = + static_cast<BrokerableAttachment*>(attachment.get()); + if (brokerable_attachment->GetBrokerableType() != + BrokerableAttachment::WIN_HANDLE) { + return false; + } + IPC::internal::HandleAttachmentWin* handle_attachment = + static_cast<IPC::internal::HandleAttachmentWin*>(brokerable_attachment); + r->set_handle(handle_attachment->get_handle()); + return true; +} + +// static +void ParamTraits<HandleWin>::Log(const param_type& p, std::string* l) { + l->append(base::StringPrintf("0x%X", p.get_handle())); + l->append(base::IntToString(p.get_permissions())); +} + +} // namespace IPC diff --git a/ipc/handle_win.h b/ipc/handle_win.h new file mode 100644 index 0000000..f5f0263 --- /dev/null +++ b/ipc/handle_win.h @@ -0,0 +1,52 @@ +// 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. + +#ifndef IPC_HANDLE_WIN_H_ +#define IPC_HANDLE_WIN_H_ + +#include <windows.h> + +#include "ipc/ipc_export.h" +#include "ipc/ipc_message_macros.h" + +namespace IPC { + +// HandleWin is a wrapper around a Windows HANDLE that can be transported +// across Chrome IPC channels that support attachment brokering. The HANDLE will +// be duplicated into the destination process. +class IPC_EXPORT HandleWin { + public: + enum Permissions { + // A placeholder value to be used by the receiving IPC channel, since the + // permissions information is only used by the broker process. + INVALID, + // The new HANDLE will have the same permissions as the old HANDLE. + DUPLICATE, + // The new HANDLE will have file read and write permissions. + FILE_READ_WRITE, + MAX_PERMISSIONS = FILE_READ_WRITE + }; + + HandleWin(const HANDLE& handle, Permissions permissions); + + HANDLE get_handle() const { return handle_; } + void set_handle(HANDLE handle) { handle_ = handle; } + Permissions get_permissions() const { return permissions_; } + + private: + HANDLE handle_; + Permissions permissions_; +}; + +template <> +struct IPC_EXPORT ParamTraits<HandleWin> { + typedef HandleWin param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +} // namespace IPC + +#endif // IPC_HANDLE_WIN_H_ diff --git a/ipc/ipc.gypi b/ipc/ipc.gypi index ce9ffda..beb0a6a 100644 --- a/ipc/ipc.gypi +++ b/ipc/ipc.gypi @@ -26,6 +26,8 @@ 'brokerable_attachment.h', 'handle_attachment_win.cc', 'handle_attachment_win.h', + 'handle_win.cc', + 'handle_win.h', 'ipc_channel.cc', 'ipc_channel.h', 'ipc_channel_factory.cc', |