OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/memory/shared_memory.h" |
| 14 #include "base/memory/shared_memory_handle.h" |
| 15 #include "base/win/scoped_handle.h" |
13 #include "ipc/attachment_broker_privileged_win.h" | 16 #include "ipc/attachment_broker_privileged_win.h" |
14 #include "ipc/attachment_broker_unprivileged_win.h" | 17 #include "ipc/attachment_broker_unprivileged_win.h" |
15 #include "ipc/handle_attachment_win.h" | 18 #include "ipc/handle_attachment_win.h" |
16 #include "ipc/handle_win.h" | 19 #include "ipc/handle_win.h" |
17 #include "ipc/ipc_listener.h" | 20 #include "ipc/ipc_listener.h" |
18 #include "ipc/ipc_message.h" | 21 #include "ipc/ipc_message.h" |
19 #include "ipc/ipc_test_base.h" | 22 #include "ipc/ipc_test_base.h" |
20 #include "ipc/ipc_test_messages.h" | 23 #include "ipc/ipc_test_messages.h" |
21 | 24 |
22 namespace { | 25 namespace { |
23 | 26 |
| 27 using base::win::ScopedHandle; |
| 28 |
24 const char kDataBuffer[] = "This is some test data to write to the file."; | 29 const char kDataBuffer[] = "This is some test data to write to the file."; |
| 30 const size_t kSharedMemorySize = 20000; |
25 | 31 |
26 // Returns the contents of the file represented by |h| as a std::string. | 32 // Returns the contents of the file represented by |h| as a std::string. |
27 std::string ReadFromFile(HANDLE h) { | 33 std::string ReadFromFile(HANDLE h) { |
28 SetFilePointer(h, 0, nullptr, FILE_BEGIN); | 34 SetFilePointer(h, 0, nullptr, FILE_BEGIN); |
29 char buffer[100]; | 35 char buffer[100]; |
30 DWORD bytes_read; | 36 DWORD bytes_read; |
31 BOOL success = ::ReadFile(h, buffer, static_cast<DWORD>(strlen(kDataBuffer)), | 37 BOOL success = ::ReadFile(h, buffer, static_cast<DWORD>(strlen(kDataBuffer)), |
32 &bytes_read, nullptr); | 38 &bytes_read, nullptr); |
33 return success ? std::string(buffer, bytes_read) : std::string(); | 39 return success ? std::string(buffer, bytes_read) : std::string(); |
34 } | 40 } |
35 | 41 |
36 HANDLE GetHandleFromBrokeredAttachment( | 42 ScopedHandle GetHandleFromBrokeredAttachment( |
37 const scoped_refptr<IPC::BrokerableAttachment>& attachment) { | 43 const scoped_refptr<IPC::BrokerableAttachment>& attachment) { |
38 if (attachment->GetType() != | 44 if (attachment->GetType() != |
39 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) { | 45 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) { |
40 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT."; | 46 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT."; |
41 return nullptr; | 47 return ScopedHandle(nullptr); |
42 } | 48 } |
43 | 49 |
44 if (attachment->GetBrokerableType() != | 50 if (attachment->GetBrokerableType() != |
45 IPC::BrokerableAttachment::WIN_HANDLE) { | 51 IPC::BrokerableAttachment::WIN_HANDLE) { |
46 LOG(INFO) << "Brokerable type not WIN_HANDLE."; | 52 LOG(INFO) << "Brokerable type not WIN_HANDLE."; |
47 return nullptr; | 53 return ScopedHandle(nullptr); |
48 } | 54 } |
49 | 55 |
50 IPC::internal::HandleAttachmentWin* received_handle_attachment = | 56 IPC::internal::HandleAttachmentWin* received_handle_attachment = |
51 static_cast<IPC::internal::HandleAttachmentWin*>(attachment.get()); | 57 static_cast<IPC::internal::HandleAttachmentWin*>(attachment.get()); |
52 return received_handle_attachment->get_handle(); | 58 ScopedHandle h(received_handle_attachment->get_handle()); |
| 59 received_handle_attachment->reset_handle_ownership(); |
| 60 return h; |
53 } | 61 } |
54 | 62 |
55 // |message| must be deserializable as a TestHandleWinMsg. Returns the HANDLE, | 63 // |message| must be deserializable as a TestHandleWinMsg. Returns the HANDLE, |
56 // or nullptr if deserialization failed. | 64 // or nullptr if deserialization failed. |
57 HANDLE GetHandleFromTestHandleWinMsg(const IPC::Message& message) { | 65 ScopedHandle GetHandleFromTestHandleWinMsg(const IPC::Message& message) { |
| 66 // Expect a message with a brokered attachment. |
| 67 if (!message.HasBrokerableAttachments()) { |
| 68 LOG(INFO) << "Message missing brokerable attachment."; |
| 69 return ScopedHandle(nullptr); |
| 70 } |
| 71 |
| 72 TestHandleWinMsg::Schema::Param p; |
| 73 bool success = TestHandleWinMsg::Read(&message, &p); |
| 74 if (!success) { |
| 75 LOG(INFO) << "Failed to deserialize message."; |
| 76 return ScopedHandle(nullptr); |
| 77 } |
| 78 |
| 79 IPC::HandleWin handle_win = base::get<1>(p); |
| 80 return ScopedHandle(handle_win.get_handle()); |
| 81 } |
| 82 |
| 83 // Returns a mapped, shared memory region based on the handle in |message|. |
| 84 scoped_ptr<base::SharedMemory> GetSharedMemoryFromSharedMemoryHandleMsg1( |
| 85 const IPC::Message& message, |
| 86 size_t size) { |
58 // Expect a message with a brokered attachment. | 87 // Expect a message with a brokered attachment. |
59 if (!message.HasBrokerableAttachments()) { | 88 if (!message.HasBrokerableAttachments()) { |
60 LOG(INFO) << "Message missing brokerable attachment."; | 89 LOG(INFO) << "Message missing brokerable attachment."; |
61 return nullptr; | 90 return nullptr; |
62 } | 91 } |
63 | 92 |
64 TestHandleWinMsg::Schema::Param p; | 93 TestSharedMemoryHandleMsg1::Schema::Param p; |
65 bool success = TestHandleWinMsg::Read(&message, &p); | 94 bool success = TestSharedMemoryHandleMsg1::Read(&message, &p); |
66 if (!success) { | 95 if (!success) { |
67 LOG(INFO) << "Failed to deserialize message."; | 96 LOG(INFO) << "Failed to deserialize message."; |
68 return nullptr; | 97 return nullptr; |
69 } | 98 } |
70 | 99 |
71 IPC::HandleWin handle_win = base::get<1>(p); | 100 base::SharedMemoryHandle handle = base::get<0>(p); |
72 return handle_win.get_handle(); | 101 scoped_ptr<base::SharedMemory> shared_memory( |
| 102 new base::SharedMemory(handle, false)); |
| 103 |
| 104 shared_memory->Map(size); |
| 105 return std::move(shared_memory); |
73 } | 106 } |
74 | 107 |
75 // |message| must be deserializable as a TestTwoHandleWinMsg. Returns the | 108 // |message| must be deserializable as a TestTwoHandleWinMsg. Returns the |
76 // HANDLE, or nullptr if deserialization failed. | 109 // HANDLE, or nullptr if deserialization failed. |
77 HANDLE GetHandleFromTestTwoHandleWinMsg(const IPC::Message& message, | 110 bool GetHandleFromTestTwoHandleWinMsg(const IPC::Message& message, |
78 int index) { | 111 HANDLE* h1, |
| 112 HANDLE* h2) { |
79 // Expect a message with a brokered attachment. | 113 // Expect a message with a brokered attachment. |
80 if (!message.HasBrokerableAttachments()) { | 114 if (!message.HasBrokerableAttachments()) { |
81 LOG(INFO) << "Message missing brokerable attachment."; | 115 LOG(INFO) << "Message missing brokerable attachment."; |
82 return nullptr; | 116 return false; |
83 } | 117 } |
84 | 118 |
85 TestTwoHandleWinMsg::Schema::Param p; | 119 TestTwoHandleWinMsg::Schema::Param p; |
86 bool success = TestTwoHandleWinMsg::Read(&message, &p); | 120 bool success = TestTwoHandleWinMsg::Read(&message, &p); |
87 if (!success) { | 121 if (!success) { |
88 LOG(INFO) << "Failed to deserialize message."; | 122 LOG(INFO) << "Failed to deserialize message."; |
89 return nullptr; | 123 return false; |
90 } | 124 } |
91 | 125 |
92 IPC::HandleWin handle_win; | 126 IPC::HandleWin handle_win = base::get<0>(p); |
93 if (index == 0) | 127 *h1 = handle_win.get_handle(); |
94 handle_win = base::get<0>(p); | 128 handle_win = base::get<1>(p); |
95 else if (index == 1) | 129 *h2 = handle_win.get_handle(); |
96 handle_win = base::get<1>(p); | 130 return true; |
97 return handle_win.get_handle(); | |
98 } | 131 } |
99 | 132 |
100 // |message| must be deserializable as a TestHandleWinMsg. Returns true if the | 133 // |message| must be deserializable as a TestHandleWinMsg. Returns true if the |
101 // attached file HANDLE has contents |kDataBuffer|. | 134 // attached file HANDLE has contents |kDataBuffer|. |
102 bool CheckContentsOfTestMessage(const IPC::Message& message) { | 135 bool CheckContentsOfTestMessage(const IPC::Message& message) { |
103 HANDLE h = GetHandleFromTestHandleWinMsg(message); | 136 ScopedHandle h(GetHandleFromTestHandleWinMsg(message)); |
104 if (h == nullptr) { | 137 if (h.Get() == nullptr) { |
105 LOG(INFO) << "Failed to get handle from TestHandleWinMsg."; | 138 LOG(INFO) << "Failed to get handle from TestHandleWinMsg."; |
106 return false; | 139 return false; |
107 } | 140 } |
108 | 141 |
109 std::string contents = ReadFromFile(h); | 142 std::string contents = ReadFromFile(h.Get()); |
110 bool success = (contents == std::string(kDataBuffer)); | 143 bool success = (contents == std::string(kDataBuffer)); |
111 if (!success) { | 144 if (!success) { |
112 LOG(INFO) << "Expected contents: " << std::string(kDataBuffer); | 145 LOG(INFO) << "Expected contents: " << std::string(kDataBuffer); |
113 LOG(INFO) << "Read contents: " << contents; | 146 LOG(INFO) << "Read contents: " << contents; |
114 } | 147 } |
115 return success; | 148 return success; |
116 } | 149 } |
117 | 150 |
118 // Returns 0 on error. | 151 // Returns 0 on error. |
119 DWORD GetCurrentProcessHandleCount() { | 152 DWORD GetCurrentProcessHandleCount() { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 HANDLE h = CreateTempFile(); | 397 HANDLE h = CreateTempFile(); |
365 SendMessageWithAttachment(h); | 398 SendMessageWithAttachment(h); |
366 base::MessageLoop::current()->Run(); | 399 base::MessageLoop::current()->Run(); |
367 | 400 |
368 // Get the received attachment. | 401 // Get the received attachment. |
369 IPC::BrokerableAttachment::AttachmentId* id = get_observer()->get_id(); | 402 IPC::BrokerableAttachment::AttachmentId* id = get_observer()->get_id(); |
370 scoped_refptr<IPC::BrokerableAttachment> received_attachment; | 403 scoped_refptr<IPC::BrokerableAttachment> received_attachment; |
371 get_broker()->GetAttachmentWithId(*id, &received_attachment); | 404 get_broker()->GetAttachmentWithId(*id, &received_attachment); |
372 ASSERT_NE(received_attachment.get(), nullptr); | 405 ASSERT_NE(received_attachment.get(), nullptr); |
373 | 406 |
374 // Check that it's the same entry in the HANDLE table. | 407 // Check that it's a different entry in the HANDLE table. |
375 HANDLE h2 = GetHandleFromBrokeredAttachment(received_attachment); | 408 ScopedHandle h2(GetHandleFromBrokeredAttachment(received_attachment)); |
376 EXPECT_EQ(h2, h); | 409 EXPECT_NE(h2.Get(), h); |
377 | 410 |
378 // And still points to the same file. | 411 // But still points to the same file. |
379 std::string contents = ReadFromFile(h); | 412 std::string contents = ReadFromFile(h2.Get()); |
380 EXPECT_EQ(contents, std::string(kDataBuffer)); | 413 EXPECT_EQ(contents, std::string(kDataBuffer)); |
381 | 414 |
382 CommonTearDown(); | 415 CommonTearDown(); |
383 } | 416 } |
384 | 417 |
385 // Similar to SendHandle, but sends a message with two instances of the same | 418 // Similar to SendHandle, but sends a message with two instances of the same |
386 // handle. | 419 // handle. |
387 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendTwoHandles) { | 420 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendTwoHandles) { |
388 Init("SendTwoHandles"); | 421 Init("SendTwoHandles"); |
389 | 422 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 base::MessageLoop::current()->Run(); | 461 base::MessageLoop::current()->Run(); |
429 | 462 |
430 // Check the result. | 463 // Check the result. |
431 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | 464 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, |
432 get_proxy_listener()->get_reason()); | 465 get_proxy_listener()->get_reason()); |
433 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | 466 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); |
434 | 467 |
435 CommonTearDown(); | 468 CommonTearDown(); |
436 } | 469 } |
437 | 470 |
| 471 // An unprivileged process makes a shared memory region and sends it to the |
| 472 // privileged process. |
| 473 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, DISABLED_SendSharedMemoryHandle) { |
| 474 Init("SendSharedMemoryHandle"); |
| 475 |
| 476 CommonSetUp(); |
| 477 ResultListener result_listener; |
| 478 get_proxy_listener()->set_listener(&result_listener); |
| 479 |
| 480 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); |
| 481 shared_memory->CreateAndMapAnonymous(kSharedMemorySize); |
| 482 memcpy(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer)); |
| 483 sender()->Send(new TestSharedMemoryHandleMsg1(shared_memory->handle())); |
| 484 base::MessageLoop::current()->Run(); |
| 485 |
| 486 // Check the result. |
| 487 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, |
| 488 get_proxy_listener()->get_reason()); |
| 489 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); |
| 490 |
| 491 CommonTearDown(); |
| 492 } |
| 493 |
438 using OnMessageReceivedCallback = void (*)(IPC::Sender* sender, | 494 using OnMessageReceivedCallback = void (*)(IPC::Sender* sender, |
439 const IPC::Message& message); | 495 const IPC::Message& message); |
440 | 496 |
441 int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback, | 497 int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback, |
442 const char* channel_name) { | 498 const char* channel_name) { |
443 LOG(INFO) << "Privileged process start."; | 499 LOG(INFO) << "Privileged process start."; |
444 base::MessageLoopForIO main_message_loop; | 500 base::MessageLoopForIO main_message_loop; |
445 ProxyListener listener; | 501 ProxyListener listener; |
446 | 502 |
447 // Set up IPC channel. | 503 // Set up IPC channel. |
(...skipping 26 matching lines...) Expand all Loading... |
474 bool success = CheckContentsOfTestMessage(message); | 530 bool success = CheckContentsOfTestMessage(message); |
475 SendControlMessage(sender, success); | 531 SendControlMessage(sender, success); |
476 } | 532 } |
477 | 533 |
478 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandle) { | 534 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandle) { |
479 return CommonPrivilegedProcessMain(&SendHandleCallback, "SendHandle"); | 535 return CommonPrivilegedProcessMain(&SendHandleCallback, "SendHandle"); |
480 } | 536 } |
481 | 537 |
482 void SendHandleWithoutPermissionsCallback(IPC::Sender* sender, | 538 void SendHandleWithoutPermissionsCallback(IPC::Sender* sender, |
483 const IPC::Message& message) { | 539 const IPC::Message& message) { |
484 HANDLE h = GetHandleFromTestHandleWinMsg(message); | 540 ScopedHandle h(GetHandleFromTestHandleWinMsg(message)); |
485 if (h != nullptr) { | 541 if (h.Get() != nullptr) { |
486 SetFilePointer(h, 0, nullptr, FILE_BEGIN); | 542 SetFilePointer(h.Get(), 0, nullptr, FILE_BEGIN); |
487 | 543 |
488 char buffer[100]; | 544 char buffer[100]; |
489 DWORD bytes_read; | 545 DWORD bytes_read; |
490 BOOL success = | 546 BOOL success = |
491 ::ReadFile(h, buffer, static_cast<DWORD>(strlen(kDataBuffer)), | 547 ::ReadFile(h.Get(), buffer, static_cast<DWORD>(strlen(kDataBuffer)), |
492 &bytes_read, nullptr); | 548 &bytes_read, nullptr); |
493 if (!success && GetLastError() == ERROR_ACCESS_DENIED) { | 549 if (!success && GetLastError() == ERROR_ACCESS_DENIED) { |
494 SendControlMessage(sender, true); | 550 SendControlMessage(sender, true); |
495 return; | 551 return; |
496 } | 552 } |
497 } | 553 } |
498 | 554 |
499 SendControlMessage(sender, false); | 555 SendControlMessage(sender, false); |
500 } | 556 } |
501 | 557 |
502 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleWithoutPermissions) { | 558 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleWithoutPermissions) { |
503 return CommonPrivilegedProcessMain(&SendHandleWithoutPermissionsCallback, | 559 return CommonPrivilegedProcessMain(&SendHandleWithoutPermissionsCallback, |
504 "SendHandleWithoutPermissions"); | 560 "SendHandleWithoutPermissions"); |
505 } | 561 } |
506 | 562 |
507 void SendHandleToSelfCallback(IPC::Sender* sender, const IPC::Message&) { | 563 void SendHandleToSelfCallback(IPC::Sender* sender, const IPC::Message&) { |
508 // Do nothing special. The default behavior already runs the | 564 // Do nothing special. The default behavior already runs the |
509 // AttachmentBrokerPrivilegedWin. | 565 // AttachmentBrokerPrivilegedWin. |
510 } | 566 } |
511 | 567 |
512 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleToSelf) { | 568 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleToSelf) { |
513 return CommonPrivilegedProcessMain(&SendHandleToSelfCallback, | 569 return CommonPrivilegedProcessMain(&SendHandleToSelfCallback, |
514 "SendHandleToSelf"); | 570 "SendHandleToSelf"); |
515 } | 571 } |
516 | 572 |
517 void SendTwoHandlesCallback(IPC::Sender* sender, const IPC::Message& message) { | 573 void SendTwoHandlesCallback(IPC::Sender* sender, const IPC::Message& message) { |
518 // Check for two handles. | 574 // Check for two handles. |
519 HANDLE h1 = GetHandleFromTestTwoHandleWinMsg(message, 0); | 575 HANDLE h1, h2; |
520 HANDLE h2 = GetHandleFromTestTwoHandleWinMsg(message, 1); | 576 EXPECT_TRUE(GetHandleFromTestTwoHandleWinMsg(message, &h1, &h2)); |
521 if (h1 == nullptr || h2 == nullptr) { | 577 if (h1 == nullptr || h2 == nullptr) { |
522 SendControlMessage(sender, false); | 578 SendControlMessage(sender, false); |
523 return; | 579 return; |
524 } | 580 } |
525 | 581 |
526 // Check that their contents are correct. | 582 // Check that their contents are correct. |
527 std::string contents1 = ReadFromFile(h1); | 583 std::string contents1 = ReadFromFile(h1); |
528 std::string contents2 = ReadFromFile(h2); | 584 std::string contents2 = ReadFromFile(h2); |
529 if (contents1 != std::string(kDataBuffer) || | 585 if (contents1 != std::string(kDataBuffer) || |
530 contents2 != std::string(kDataBuffer)) { | 586 contents2 != std::string(kDataBuffer)) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 LOG(INFO) << "Received second message."; | 628 LOG(INFO) << "Received second message."; |
573 SendControlMessage(sender, success); | 629 SendControlMessage(sender, success); |
574 } | 630 } |
575 } | 631 } |
576 | 632 |
577 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleTwice) { | 633 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleTwice) { |
578 return CommonPrivilegedProcessMain(&SendHandleTwiceCallback, | 634 return CommonPrivilegedProcessMain(&SendHandleTwiceCallback, |
579 "SendHandleTwice"); | 635 "SendHandleTwice"); |
580 } | 636 } |
581 | 637 |
| 638 void SendSharedMemoryHandleCallback(IPC::Sender* sender, |
| 639 const IPC::Message& message) { |
| 640 scoped_ptr<base::SharedMemory> shared_memory = |
| 641 GetSharedMemoryFromSharedMemoryHandleMsg1(message, kSharedMemorySize); |
| 642 bool success = |
| 643 memcmp(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer)) == 0; |
| 644 SendControlMessage(sender, success); |
| 645 } |
| 646 |
| 647 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandle) { |
| 648 return CommonPrivilegedProcessMain(&SendSharedMemoryHandleCallback, |
| 649 "SendSharedMemoryHandle"); |
| 650 } |
| 651 |
582 } // namespace | 652 } // namespace |
OLD | NEW |