blob: 3c8df8e806468a4ec53c1a5095ab728ad6901bc3 [file] [log] [blame]
erikchenc04ab34c2015-07-27 20:28:201// Copyright 2015 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 "build/build_config.h"
6
7#include <windows.h>
8
danakj03de39b22016-04-23 04:21:099#include <memory>
tzik55e3e4d2016-03-08 05:47:4410#include <tuple>
11
erikchenc04ab34c2015-07-27 20:28:2012#include "base/files/file_path.h"
13#include "base/files/file_util.h"
14#include "base/files/scoped_temp_dir.h"
erikchen3d87ecf72016-01-08 02:17:0415#include "base/memory/shared_memory.h"
16#include "base/memory/shared_memory_handle.h"
17#include "base/win/scoped_handle.h"
erikchenc04ab34c2015-07-27 20:28:2018#include "ipc/attachment_broker_privileged_win.h"
erikchen484c00842015-07-28 23:25:4419#include "ipc/attachment_broker_unprivileged_win.h"
erikchenc04ab34c2015-07-27 20:28:2020#include "ipc/handle_attachment_win.h"
erikchen959039d2015-08-11 21:17:4721#include "ipc/handle_win.h"
erikchenc04ab34c2015-07-27 20:28:2022#include "ipc/ipc_listener.h"
23#include "ipc/ipc_message.h"
24#include "ipc/ipc_test_base.h"
erikchen98daa732015-09-25 18:30:0325#include "ipc/ipc_test_messages.h"
erikchenc04ab34c2015-07-27 20:28:2026
27namespace {
28
erikchen3d87ecf72016-01-08 02:17:0429using base::win::ScopedHandle;
30
erikchenc04ab34c2015-07-27 20:28:2031const char kDataBuffer[] = "This is some test data to write to the file.";
erikchen3d87ecf72016-01-08 02:17:0432const size_t kSharedMemorySize = 20000;
erikchenc04ab34c2015-07-27 20:28:2033
34// Returns the contents of the file represented by |h| as a std::string.
35std::string ReadFromFile(HANDLE h) {
36 SetFilePointer(h, 0, nullptr, FILE_BEGIN);
37 char buffer[100];
38 DWORD bytes_read;
39 BOOL success = ::ReadFile(h, buffer, static_cast<DWORD>(strlen(kDataBuffer)),
40 &bytes_read, nullptr);
41 return success ? std::string(buffer, bytes_read) : std::string();
42}
43
erikchen3d87ecf72016-01-08 02:17:0444ScopedHandle GetHandleFromBrokeredAttachment(
erikchenc04ab34c2015-07-27 20:28:2045 const scoped_refptr<IPC::BrokerableAttachment>& attachment) {
46 if (attachment->GetType() !=
erikchen98daa732015-09-25 18:30:0347 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) {
48 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT.";
erikchen3d87ecf72016-01-08 02:17:0449 return ScopedHandle(nullptr);
erikchen98daa732015-09-25 18:30:0350 }
51
52 if (attachment->GetBrokerableType() !=
53 IPC::BrokerableAttachment::WIN_HANDLE) {
54 LOG(INFO) << "Brokerable type not WIN_HANDLE.";
erikchen3d87ecf72016-01-08 02:17:0455 return ScopedHandle(nullptr);
erikchen98daa732015-09-25 18:30:0356 }
57
erikchenc04ab34c2015-07-27 20:28:2058 IPC::internal::HandleAttachmentWin* received_handle_attachment =
59 static_cast<IPC::internal::HandleAttachmentWin*>(attachment.get());
erikchen3d87ecf72016-01-08 02:17:0460 ScopedHandle h(received_handle_attachment->get_handle());
61 received_handle_attachment->reset_handle_ownership();
62 return h;
erikchenc04ab34c2015-07-27 20:28:2063}
64
erikchen98daa732015-09-25 18:30:0365// |message| must be deserializable as a TestHandleWinMsg. Returns the HANDLE,
66// or nullptr if deserialization failed.
erikchen3d87ecf72016-01-08 02:17:0467ScopedHandle GetHandleFromTestHandleWinMsg(const IPC::Message& message) {
erikchen98daa732015-09-25 18:30:0368 // Expect a message with a brokered attachment.
69 if (!message.HasBrokerableAttachments()) {
70 LOG(INFO) << "Message missing brokerable attachment.";
erikchen3d87ecf72016-01-08 02:17:0471 return ScopedHandle(nullptr);
erikchen98daa732015-09-25 18:30:0372 }
73
74 TestHandleWinMsg::Schema::Param p;
75 bool success = TestHandleWinMsg::Read(&message, &p);
76 if (!success) {
77 LOG(INFO) << "Failed to deserialize message.";
erikchen3d87ecf72016-01-08 02:17:0478 return ScopedHandle(nullptr);
erikchen98daa732015-09-25 18:30:0379 }
80
tzik55e3e4d2016-03-08 05:47:4481 IPC::HandleWin handle_win = std::get<1>(p);
erikchen3d87ecf72016-01-08 02:17:0482 return ScopedHandle(handle_win.get_handle());
erikchen98daa732015-09-25 18:30:0383}
84
erikchen3d87ecf72016-01-08 02:17:0485// Returns a mapped, shared memory region based on the handle in |message|.
danakj03de39b22016-04-23 04:21:0986std::unique_ptr<base::SharedMemory> GetSharedMemoryFromSharedMemoryHandleMsg1(
erikchen3d87ecf72016-01-08 02:17:0487 const IPC::Message& message,
88 size_t size) {
erikchen98daa732015-09-25 18:30:0389 // Expect a message with a brokered attachment.
90 if (!message.HasBrokerableAttachments()) {
91 LOG(INFO) << "Message missing brokerable attachment.";
92 return nullptr;
93 }
94
erikchen3d87ecf72016-01-08 02:17:0495 TestSharedMemoryHandleMsg1::Schema::Param p;
96 bool success = TestSharedMemoryHandleMsg1::Read(&message, &p);
erikchen98daa732015-09-25 18:30:0397 if (!success) {
98 LOG(INFO) << "Failed to deserialize message.";
99 return nullptr;
100 }
101
tzik55e3e4d2016-03-08 05:47:44102 base::SharedMemoryHandle handle = std::get<0>(p);
danakj03de39b22016-04-23 04:21:09103 std::unique_ptr<base::SharedMemory> shared_memory(
erikchen3d87ecf72016-01-08 02:17:04104 new base::SharedMemory(handle, false));
105
106 shared_memory->Map(size);
Hans Wennborgb7da2472016-01-08 14:33:52107 return shared_memory;
erikchen3d87ecf72016-01-08 02:17:04108}
109
110// |message| must be deserializable as a TestTwoHandleWinMsg. Returns the
111// HANDLE, or nullptr if deserialization failed.
112bool GetHandleFromTestTwoHandleWinMsg(const IPC::Message& message,
113 HANDLE* h1,
114 HANDLE* h2) {
115 // Expect a message with a brokered attachment.
116 if (!message.HasBrokerableAttachments()) {
117 LOG(INFO) << "Message missing brokerable attachment.";
118 return false;
119 }
120
121 TestTwoHandleWinMsg::Schema::Param p;
122 bool success = TestTwoHandleWinMsg::Read(&message, &p);
123 if (!success) {
124 LOG(INFO) << "Failed to deserialize message.";
125 return false;
126 }
127
tzik55e3e4d2016-03-08 05:47:44128 IPC::HandleWin handle_win = std::get<0>(p);
erikchen3d87ecf72016-01-08 02:17:04129 *h1 = handle_win.get_handle();
tzik55e3e4d2016-03-08 05:47:44130 handle_win = std::get<1>(p);
erikchen3d87ecf72016-01-08 02:17:04131 *h2 = handle_win.get_handle();
132 return true;
erikchen98daa732015-09-25 18:30:03133}
134
135// |message| must be deserializable as a TestHandleWinMsg. Returns true if the
136// attached file HANDLE has contents |kDataBuffer|.
137bool CheckContentsOfTestMessage(const IPC::Message& message) {
erikchen3d87ecf72016-01-08 02:17:04138 ScopedHandle h(GetHandleFromTestHandleWinMsg(message));
139 if (h.Get() == nullptr) {
erikchen98daa732015-09-25 18:30:03140 LOG(INFO) << "Failed to get handle from TestHandleWinMsg.";
erikchenc04ab34c2015-07-27 20:28:20141 return false;
erikchen98daa732015-09-25 18:30:03142 }
erikchenc04ab34c2015-07-27 20:28:20143
erikchen3d87ecf72016-01-08 02:17:04144 std::string contents = ReadFromFile(h.Get());
erikchen98daa732015-09-25 18:30:03145 bool success = (contents == std::string(kDataBuffer));
146 if (!success) {
147 LOG(INFO) << "Expected contents: " << std::string(kDataBuffer);
148 LOG(INFO) << "Read contents: " << contents;
149 }
150 return success;
erikchenc04ab34c2015-07-27 20:28:20151}
152
erikchen17b34832015-12-04 21:20:12153// Returns 0 on error.
154DWORD GetCurrentProcessHandleCount() {
155 DWORD handle_count = 0;
156 BOOL success = ::GetProcessHandleCount(::GetCurrentProcess(), &handle_count);
157 return success ? handle_count : 0;
158}
159
erikchenc04ab34c2015-07-27 20:28:20160enum TestResult {
161 RESULT_UNKNOWN,
162 RESULT_SUCCESS,
163 RESULT_FAILURE,
164};
165
166// Once the test is finished, send a control message to the parent process with
167// the result. The message may require the runloop to be run before its
168// dispatched.
169void SendControlMessage(IPC::Sender* sender, bool success) {
170 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
171 TestResult result = success ? RESULT_SUCCESS : RESULT_FAILURE;
172 message->WriteInt(result);
173 sender->Send(message);
174}
175
176class MockObserver : public IPC::AttachmentBroker::Observer {
177 public:
178 void ReceivedBrokerableAttachmentWithId(
179 const IPC::BrokerableAttachment::AttachmentId& id) override {
180 id_ = id;
181 }
182 IPC::BrokerableAttachment::AttachmentId* get_id() { return &id_; }
183
184 private:
185 IPC::BrokerableAttachment::AttachmentId id_;
186};
187
188// Forwards all messages to |listener_|. Quits the message loop after a
189// message is received, or the channel has an error.
190class ProxyListener : public IPC::Listener {
191 public:
erikchen98daa732015-09-25 18:30:03192 ProxyListener() : listener_(nullptr), reason_(MESSAGE_RECEIVED) {}
erikchenc04ab34c2015-07-27 20:28:20193 ~ProxyListener() override {}
194
195 // The reason for exiting the message loop.
196 enum Reason { MESSAGE_RECEIVED, CHANNEL_ERROR };
197
198 bool OnMessageReceived(const IPC::Message& message) override {
erikchen98daa732015-09-25 18:30:03199 bool result = false;
200 if (listener_)
201 result = listener_->OnMessageReceived(message);
erikchenc04ab34c2015-07-27 20:28:20202 reason_ = MESSAGE_RECEIVED;
erikchen98daa732015-09-25 18:30:03203 messages_.push_back(message);
204 base::MessageLoop::current()->QuitNow();
erikchenc04ab34c2015-07-27 20:28:20205 return result;
206 }
207
208 void OnChannelError() override {
209 reason_ = CHANNEL_ERROR;
erikchen98daa732015-09-25 18:30:03210 base::MessageLoop::current()->QuitNow();
erikchenc04ab34c2015-07-27 20:28:20211 }
212
213 void set_listener(IPC::Listener* listener) { listener_ = listener; }
214 Reason get_reason() { return reason_; }
erikchen98daa732015-09-25 18:30:03215 IPC::Message get_first_message() { return messages_[0]; }
216 void pop_first_message() { messages_.erase(messages_.begin()); }
217 bool has_message() { return !messages_.empty(); }
erikchenc04ab34c2015-07-27 20:28:20218
219 private:
220 IPC::Listener* listener_;
221 Reason reason_;
erikchen98daa732015-09-25 18:30:03222 std::vector<IPC::Message> messages_;
erikchenc04ab34c2015-07-27 20:28:20223};
224
225// Waits for a result to be sent over the channel. Quits the message loop
226// after a message is received, or the channel has an error.
227class ResultListener : public IPC::Listener {
228 public:
229 ResultListener() : result_(RESULT_UNKNOWN) {}
230 ~ResultListener() override {}
231
232 bool OnMessageReceived(const IPC::Message& message) override {
233 base::PickleIterator iter(message);
234
235 int result;
236 EXPECT_TRUE(iter.ReadInt(&result));
237 result_ = static_cast<TestResult>(result);
238 return true;
239 }
240
241 TestResult get_result() { return result_; }
242
243 private:
244 TestResult result_;
245};
246
247// The parent process acts as an unprivileged process. The forked process acts
248// as the privileged process.
249class IPCAttachmentBrokerPrivilegedWinTest : public IPCTestBase {
250 public:
erikchen98daa732015-09-25 18:30:03251 IPCAttachmentBrokerPrivilegedWinTest() {}
erikchenc04ab34c2015-07-27 20:28:20252 ~IPCAttachmentBrokerPrivilegedWinTest() override {}
253
254 void SetUp() override {
255 IPCTestBase::SetUp();
256 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
257 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_path_));
258 }
259
260 void TearDown() override { IPCTestBase::TearDown(); }
261
262 // Takes ownership of |broker|. Has no effect if called after CommonSetUp().
erikchen484c00842015-07-28 23:25:44263 void set_broker(IPC::AttachmentBrokerUnprivilegedWin* broker) {
264 broker_.reset(broker);
265 }
erikchenc04ab34c2015-07-27 20:28:20266
267 void CommonSetUp() {
erikchen90971902016-04-25 23:45:31268 PreConnectSetUp();
269 PostConnectSetUp();
270 }
271
272 // All of setup before the channel is connected.
273 void PreConnectSetUp() {
erikchenc04ab34c2015-07-27 20:28:20274 if (!broker_.get())
erikchen484c00842015-07-28 23:25:44275 set_broker(new IPC::AttachmentBrokerUnprivilegedWin);
erikchen94c9b702015-11-06 21:12:36276 broker_->AddObserver(&observer_, task_runner());
erikchenc04ab34c2015-07-27 20:28:20277 CreateChannel(&proxy_listener_);
erikchen86662872016-02-17 04:09:14278 broker_->RegisterBrokerCommunicationChannel(channel());
erikchen90971902016-04-25 23:45:31279 }
280
281 // All of setup including the connection and everything after.
282 void PostConnectSetUp() {
erikchenc04ab34c2015-07-27 20:28:20283 ASSERT_TRUE(ConnectChannel());
284 ASSERT_TRUE(StartClient());
erikchen17b34832015-12-04 21:20:12285
286 handle_count_ = GetCurrentProcessHandleCount();
287 EXPECT_NE(handle_count_, 0u);
erikchenc04ab34c2015-07-27 20:28:20288 }
289
290 void CommonTearDown() {
erikchen17b34832015-12-04 21:20:12291 EXPECT_EQ(handle_count_, handle_count_);
292
erikchenc04ab34c2015-07-27 20:28:20293 // Close the channel so the client's OnChannelError() gets fired.
294 channel()->Close();
295
296 EXPECT_TRUE(WaitForClientShutdown());
297 DestroyChannel();
298 broker_.reset();
299 }
300
301 HANDLE CreateTempFile() {
302 EXPECT_NE(-1, WriteFile(temp_path_, kDataBuffer,
303 static_cast<int>(strlen(kDataBuffer))));
304
305 HANDLE h =
306 CreateFile(temp_path_.value().c_str(), GENERIC_READ | GENERIC_WRITE, 0,
307 nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
308 EXPECT_NE(h, INVALID_HANDLE_VALUE);
309 return h;
310 }
311
312 void SendMessageWithAttachment(HANDLE h) {
erikchen98daa732015-09-25 18:30:03313 IPC::HandleWin handle_win(h, IPC::HandleWin::FILE_READ_WRITE);
314 IPC::Message* message = new TestHandleWinMsg(100, handle_win, 200);
erikchenc04ab34c2015-07-27 20:28:20315 sender()->Send(message);
316 }
317
318 ProxyListener* get_proxy_listener() { return &proxy_listener_; }
erikchen484c00842015-07-28 23:25:44319 IPC::AttachmentBrokerUnprivilegedWin* get_broker() { return broker_.get(); }
erikchenc04ab34c2015-07-27 20:28:20320 MockObserver* get_observer() { return &observer_; }
321
322 private:
323 base::ScopedTempDir temp_dir_;
324 base::FilePath temp_path_;
erikchenc04ab34c2015-07-27 20:28:20325 ProxyListener proxy_listener_;
danakj03de39b22016-04-23 04:21:09326 std::unique_ptr<IPC::AttachmentBrokerUnprivilegedWin> broker_;
erikchenc04ab34c2015-07-27 20:28:20327 MockObserver observer_;
erikchen17b34832015-12-04 21:20:12328 DWORD handle_count_;
erikchenc04ab34c2015-07-27 20:28:20329};
330
331// A broker which always sets the current process as the destination process
332// for attachments.
erikchen484c00842015-07-28 23:25:44333class MockBroker : public IPC::AttachmentBrokerUnprivilegedWin {
erikchenc04ab34c2015-07-27 20:28:20334 public:
335 MockBroker() {}
336 ~MockBroker() override {}
erikchena03dde6f2015-10-29 22:37:04337 bool SendAttachmentToProcess(
338 const scoped_refptr<IPC::BrokerableAttachment>& attachment,
339 base::ProcessId destination_process) override {
erikchen484c00842015-07-28 23:25:44340 return IPC::AttachmentBrokerUnprivilegedWin::SendAttachmentToProcess(
erikchenc04ab34c2015-07-27 20:28:20341 attachment, base::Process::Current().Pid());
342 }
343};
344
345// An unprivileged process makes a file HANDLE, and writes a string to it. The
346// file HANDLE is sent to the privileged process using the attachment broker.
347// The privileged process dups the HANDLE into its own HANDLE table. This test
348// checks that the file has the same contents in the privileged process.
erikchenee444502015-12-04 17:20:37349TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandle) {
erikchenc04ab34c2015-07-27 20:28:20350 Init("SendHandle");
351
352 CommonSetUp();
353 ResultListener result_listener;
354 get_proxy_listener()->set_listener(&result_listener);
355
356 HANDLE h = CreateTempFile();
357 SendMessageWithAttachment(h);
358 base::MessageLoop::current()->Run();
359
360 // Check the result.
361 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
362 get_proxy_listener()->get_reason());
363 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS);
364
365 CommonTearDown();
366}
367
368// Similar to SendHandle, except the file HANDLE attached to the message has
369// neither read nor write permissions.
erikchen44067ac2015-09-04 02:35:49370TEST_F(IPCAttachmentBrokerPrivilegedWinTest,
erikchenee444502015-12-04 17:20:37371 SendHandleWithoutPermissions) {
erikchenc04ab34c2015-07-27 20:28:20372 Init("SendHandleWithoutPermissions");
373
374 CommonSetUp();
375 ResultListener result_listener;
376 get_proxy_listener()->set_listener(&result_listener);
377
378 HANDLE h = CreateTempFile();
379 HANDLE h2;
380 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(),
381 &h2, 0, FALSE, DUPLICATE_CLOSE_SOURCE);
382 ASSERT_TRUE(result);
erikchen98daa732015-09-25 18:30:03383 IPC::HandleWin handle_win(h2, IPC::HandleWin::DUPLICATE);
384 IPC::Message* message = new TestHandleWinMsg(100, handle_win, 200);
385 sender()->Send(message);
erikchenc04ab34c2015-07-27 20:28:20386 base::MessageLoop::current()->Run();
387
388 // Check the result.
389 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
390 get_proxy_listener()->get_reason());
391 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS);
392
393 CommonTearDown();
394}
395
396// Similar to SendHandle, except the attachment's destination process is this
397// process. This is an unrealistic scenario, but simulates an unprivileged
398// process sending an attachment to another unprivileged process.
erikchenee444502015-12-04 17:20:37399TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleToSelf) {
erikchenc04ab34c2015-07-27 20:28:20400 Init("SendHandleToSelf");
401
402 set_broker(new MockBroker);
erikchen90971902016-04-25 23:45:31403
404 PreConnectSetUp();
erikchen8c73f832015-07-30 22:26:08405 // Technically, the channel is an endpoint, but we need the proxy listener to
406 // receive the messages so that it can quit the message loop.
erikchena09b9be72015-08-10 19:22:33407 channel()->SetAttachmentBrokerEndpoint(false);
erikchen90971902016-04-25 23:45:31408 PostConnectSetUp();
erikchenc04ab34c2015-07-27 20:28:20409 get_proxy_listener()->set_listener(get_broker());
410
411 HANDLE h = CreateTempFile();
412 SendMessageWithAttachment(h);
413 base::MessageLoop::current()->Run();
414
415 // Get the received attachment.
416 IPC::BrokerableAttachment::AttachmentId* id = get_observer()->get_id();
417 scoped_refptr<IPC::BrokerableAttachment> received_attachment;
418 get_broker()->GetAttachmentWithId(*id, &received_attachment);
419 ASSERT_NE(received_attachment.get(), nullptr);
420
erikchen3d87ecf72016-01-08 02:17:04421 // Check that it's a different entry in the HANDLE table.
422 ScopedHandle h2(GetHandleFromBrokeredAttachment(received_attachment));
423 EXPECT_NE(h2.Get(), h);
erikchenc04ab34c2015-07-27 20:28:20424
erikchen3d87ecf72016-01-08 02:17:04425 // But still points to the same file.
426 std::string contents = ReadFromFile(h2.Get());
erikchenc04ab34c2015-07-27 20:28:20427 EXPECT_EQ(contents, std::string(kDataBuffer));
428
429 CommonTearDown();
430}
431
erikchen98daa732015-09-25 18:30:03432// Similar to SendHandle, but sends a message with two instances of the same
433// handle.
erikchenee444502015-12-04 17:20:37434TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendTwoHandles) {
erikchen98daa732015-09-25 18:30:03435 Init("SendTwoHandles");
erikchen959039d2015-08-11 21:17:47436
437 CommonSetUp();
438 ResultListener result_listener;
439 get_proxy_listener()->set_listener(&result_listener);
440
441 HANDLE h = CreateTempFile();
erikchen17b34832015-12-04 21:20:12442 HANDLE h2;
443 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(),
444 &h2, 0, FALSE, DUPLICATE_SAME_ACCESS);
445 ASSERT_TRUE(result);
erikchen98daa732015-09-25 18:30:03446 IPC::HandleWin handle_win1(h, IPC::HandleWin::FILE_READ_WRITE);
erikchen17b34832015-12-04 21:20:12447 IPC::HandleWin handle_win2(h2, IPC::HandleWin::FILE_READ_WRITE);
erikchen98daa732015-09-25 18:30:03448 IPC::Message* message = new TestTwoHandleWinMsg(handle_win1, handle_win2);
erikchen959039d2015-08-11 21:17:47449 sender()->Send(message);
450 base::MessageLoop::current()->Run();
451
452 // Check the result.
453 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
454 get_proxy_listener()->get_reason());
455 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS);
456
457 CommonTearDown();
458}
459
erikchen98daa732015-09-25 18:30:03460// Similar to SendHandle, but sends the same message twice.
erikchenee444502015-12-04 17:20:37461TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleTwice) {
erikchen98daa732015-09-25 18:30:03462 Init("SendHandleTwice");
463
464 CommonSetUp();
465 ResultListener result_listener;
466 get_proxy_listener()->set_listener(&result_listener);
467
468 HANDLE h = CreateTempFile();
erikchen17b34832015-12-04 21:20:12469 HANDLE h2;
470 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(),
471 &h2, 0, FALSE, DUPLICATE_SAME_ACCESS);
472 ASSERT_TRUE(result);
erikchen98daa732015-09-25 18:30:03473 SendMessageWithAttachment(h);
erikchen17b34832015-12-04 21:20:12474 SendMessageWithAttachment(h2);
erikchen98daa732015-09-25 18:30:03475 base::MessageLoop::current()->Run();
476
477 // Check the result.
478 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
479 get_proxy_listener()->get_reason());
480 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS);
481
482 CommonTearDown();
483}
484
erikchen3d87ecf72016-01-08 02:17:04485// An unprivileged process makes a shared memory region and sends it to the
486// privileged process.
erikchen0da94252016-02-03 04:44:39487TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendSharedMemoryHandle) {
erikchen3d87ecf72016-01-08 02:17:04488 Init("SendSharedMemoryHandle");
489
490 CommonSetUp();
491 ResultListener result_listener;
492 get_proxy_listener()->set_listener(&result_listener);
493
danakj03de39b22016-04-23 04:21:09494 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
erikchen3d87ecf72016-01-08 02:17:04495 shared_memory->CreateAndMapAnonymous(kSharedMemorySize);
496 memcpy(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer));
497 sender()->Send(new TestSharedMemoryHandleMsg1(shared_memory->handle()));
498 base::MessageLoop::current()->Run();
499
500 // Check the result.
501 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
502 get_proxy_listener()->get_reason());
503 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS);
504
505 CommonTearDown();
506}
507
erikchen98daa732015-09-25 18:30:03508using OnMessageReceivedCallback = void (*)(IPC::Sender* sender,
509 const IPC::Message& message);
erikchenc04ab34c2015-07-27 20:28:20510
511int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback,
512 const char* channel_name) {
erikchen98daa732015-09-25 18:30:03513 LOG(INFO) << "Privileged process start.";
erikchenc04ab34c2015-07-27 20:28:20514 base::MessageLoopForIO main_message_loop;
515 ProxyListener listener;
516
517 // Set up IPC channel.
518 IPC::AttachmentBrokerPrivilegedWin broker;
danakj03de39b22016-04-23 04:21:09519 std::unique_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
erikchen30dc2812015-09-24 03:26:38520 IPCTestBase::GetChannelName(channel_name), &listener));
erikchena91d05132016-03-21 23:19:40521 broker.RegisterCommunicationChannel(channel.get(), nullptr);
erikchenc04ab34c2015-07-27 20:28:20522 CHECK(channel->Connect());
523
erikchenc04ab34c2015-07-27 20:28:20524 while (true) {
erikchen98daa732015-09-25 18:30:03525 LOG(INFO) << "Privileged process spinning run loop.";
erikchenc04ab34c2015-07-27 20:28:20526 base::MessageLoop::current()->Run();
527 ProxyListener::Reason reason = listener.get_reason();
528 if (reason == ProxyListener::CHANNEL_ERROR)
529 break;
530
erikchen98daa732015-09-25 18:30:03531 while (listener.has_message()) {
532 LOG(INFO) << "Privileged process running callback.";
533 callback(channel.get(), listener.get_first_message());
534 LOG(INFO) << "Privileged process finishing callback.";
535 listener.pop_first_message();
536 }
erikchenc04ab34c2015-07-27 20:28:20537 }
538
erikchen98daa732015-09-25 18:30:03539 LOG(INFO) << "Privileged process end.";
erikchenc04ab34c2015-07-27 20:28:20540 return 0;
541}
542
erikchen98daa732015-09-25 18:30:03543void SendHandleCallback(IPC::Sender* sender, const IPC::Message& message) {
544 bool success = CheckContentsOfTestMessage(message);
erikchenc04ab34c2015-07-27 20:28:20545 SendControlMessage(sender, success);
546}
547
548MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandle) {
549 return CommonPrivilegedProcessMain(&SendHandleCallback, "SendHandle");
550}
551
erikchen98daa732015-09-25 18:30:03552void SendHandleWithoutPermissionsCallback(IPC::Sender* sender,
553 const IPC::Message& message) {
erikchen3d87ecf72016-01-08 02:17:04554 ScopedHandle h(GetHandleFromTestHandleWinMsg(message));
555 if (h.Get() != nullptr) {
556 SetFilePointer(h.Get(), 0, nullptr, FILE_BEGIN);
erikchenc04ab34c2015-07-27 20:28:20557
558 char buffer[100];
559 DWORD bytes_read;
560 BOOL success =
erikchen3d87ecf72016-01-08 02:17:04561 ::ReadFile(h.Get(), buffer, static_cast<DWORD>(strlen(kDataBuffer)),
erikchenc04ab34c2015-07-27 20:28:20562 &bytes_read, nullptr);
563 if (!success && GetLastError() == ERROR_ACCESS_DENIED) {
564 SendControlMessage(sender, true);
565 return;
566 }
567 }
568
569 SendControlMessage(sender, false);
570}
571
572MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleWithoutPermissions) {
573 return CommonPrivilegedProcessMain(&SendHandleWithoutPermissionsCallback,
574 "SendHandleWithoutPermissions");
575}
576
erikchen98daa732015-09-25 18:30:03577void SendHandleToSelfCallback(IPC::Sender* sender, const IPC::Message&) {
erikchenc04ab34c2015-07-27 20:28:20578 // Do nothing special. The default behavior already runs the
579 // AttachmentBrokerPrivilegedWin.
580}
581
582MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleToSelf) {
583 return CommonPrivilegedProcessMain(&SendHandleToSelfCallback,
584 "SendHandleToSelf");
585}
586
erikchen98daa732015-09-25 18:30:03587void SendTwoHandlesCallback(IPC::Sender* sender, const IPC::Message& message) {
588 // Check for two handles.
erikchen3d87ecf72016-01-08 02:17:04589 HANDLE h1, h2;
590 EXPECT_TRUE(GetHandleFromTestTwoHandleWinMsg(message, &h1, &h2));
erikchen98daa732015-09-25 18:30:03591 if (h1 == nullptr || h2 == nullptr) {
592 SendControlMessage(sender, false);
593 return;
594 }
595
596 // Check that their contents are correct.
597 std::string contents1 = ReadFromFile(h1);
598 std::string contents2 = ReadFromFile(h2);
599 if (contents1 != std::string(kDataBuffer) ||
600 contents2 != std::string(kDataBuffer)) {
601 SendControlMessage(sender, false);
602 return;
603 }
604
605 // Check that the handles point to the same file.
606 const char text[] = "katy perry";
607 DWORD bytes_written = 0;
608 SetFilePointer(h1, 0, nullptr, FILE_BEGIN);
609 BOOL success = ::WriteFile(h1, text, static_cast<DWORD>(strlen(text)),
610 &bytes_written, nullptr);
611 if (!success) {
612 SendControlMessage(sender, false);
613 return;
614 }
615
616 SetFilePointer(h2, 0, nullptr, FILE_BEGIN);
617 char buffer[100];
618 DWORD bytes_read;
619 success = ::ReadFile(h2, buffer, static_cast<DWORD>(strlen(text)),
620 &bytes_read, nullptr);
621 if (!success) {
622 SendControlMessage(sender, false);
623 return;
624 }
625 success = std::string(buffer, bytes_read) == std::string(text);
626 SendControlMessage(sender, success);
627}
628
629MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendTwoHandles) {
630 return CommonPrivilegedProcessMain(&SendTwoHandlesCallback, "SendTwoHandles");
631}
632
633void SendHandleTwiceCallback(IPC::Sender* sender, const IPC::Message& message) {
634 // We expect the same message twice.
635 static int i = 0;
636 static bool success = true;
637 success &= CheckContentsOfTestMessage(message);
638 if (i == 0) {
639 LOG(INFO) << "Received first message.";
640 ++i;
641 } else {
642 LOG(INFO) << "Received second message.";
643 SendControlMessage(sender, success);
644 }
645}
646
647MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleTwice) {
648 return CommonPrivilegedProcessMain(&SendHandleTwiceCallback,
649 "SendHandleTwice");
erikchen959039d2015-08-11 21:17:47650}
651
erikchen3d87ecf72016-01-08 02:17:04652void SendSharedMemoryHandleCallback(IPC::Sender* sender,
653 const IPC::Message& message) {
danakj03de39b22016-04-23 04:21:09654 std::unique_ptr<base::SharedMemory> shared_memory =
erikchen3d87ecf72016-01-08 02:17:04655 GetSharedMemoryFromSharedMemoryHandleMsg1(message, kSharedMemorySize);
656 bool success =
657 memcmp(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer)) == 0;
658 SendControlMessage(sender, success);
659}
660
661MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandle) {
662 return CommonPrivilegedProcessMain(&SendSharedMemoryHandleCallback,
663 "SendSharedMemoryHandle");
664}
665
erikchenc04ab34c2015-07-27 20:28:20666} // namespace