| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "mojo/edk/system/raw_channel.h" | 5 #include "mojo/edk/system/raw_channel.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/process/process.h" | 15 #include "base/process/process.h" |
| 16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
| 17 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" |
| 18 #include "base/win/scoped_handle.h" | 18 #include "base/win/scoped_handle.h" |
| 19 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
| 20 #include "mojo/edk/embedder/embedder_internal.h" | 20 #include "mojo/edk/embedder/embedder_internal.h" |
| 21 #include "mojo/edk/embedder/platform_handle.h" | 21 #include "mojo/edk/embedder/platform_handle.h" |
| 22 #include "mojo/edk/system/token_serializer_win.h" |
| 22 #include "mojo/edk/system/transport_data.h" | 23 #include "mojo/edk/system/transport_data.h" |
| 23 #include "mojo/public/cpp/system/macros.h" | 24 #include "mojo/public/cpp/system/macros.h" |
| 24 | 25 |
| 25 #define STATUS_CANCELLED 0xC0000120 | 26 #define STATUS_CANCELLED 0xC0000120 |
| 26 #define STATUS_PIPE_BROKEN 0xC000014B | 27 #define STATUS_PIPE_BROKEN 0xC000014B |
| 27 | 28 |
| 28 namespace mojo { | 29 namespace mojo { |
| 29 namespace edk { | 30 namespace edk { |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 struct MOJO_ALIGNAS(8) SerializedHandle { | |
| 34 DWORD handle_pid; | |
| 35 HANDLE handle; | |
| 36 }; | |
| 37 | |
| 38 class VistaOrHigherFunctions { | 34 class VistaOrHigherFunctions { |
| 39 public: | 35 public: |
| 40 VistaOrHigherFunctions() | 36 VistaOrHigherFunctions() |
| 41 : is_vista_or_higher_( | 37 : is_vista_or_higher_( |
| 42 base::win::GetVersion() >= base::win::VERSION_VISTA), | 38 base::win::GetVersion() >= base::win::VERSION_VISTA), |
| 43 cancel_io_ex_(nullptr), | 39 cancel_io_ex_(nullptr), |
| 44 get_file_information_by_handle_ex_(nullptr) { | 40 get_file_information_by_handle_ex_(nullptr) { |
| 45 if (!is_vista_or_higher_) | 41 if (!is_vista_or_higher_) |
| 46 return; | 42 return; |
| 47 | 43 |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 DCHECK(io_handler_); | 591 DCHECK(io_handler_); |
| 596 DCHECK(!io_handler_->pending_read()); | 592 DCHECK(!io_handler_->pending_read()); |
| 597 | 593 |
| 598 size_t bytes_read = 0; | 594 size_t bytes_read = 0; |
| 599 return Read(&bytes_read); | 595 return Read(&bytes_read); |
| 600 } | 596 } |
| 601 | 597 |
| 602 ScopedPlatformHandleVectorPtr GetReadPlatformHandles( | 598 ScopedPlatformHandleVectorPtr GetReadPlatformHandles( |
| 603 size_t num_platform_handles, | 599 size_t num_platform_handles, |
| 604 const void* platform_handle_table) override { | 600 const void* platform_handle_table) override { |
| 605 // TODO(jam): this code will have to be updated once it's used in a sandbox | |
| 606 // and the receiving process doesn't have duplicate permission for the | |
| 607 // receiver. Once there's a broker and we have a connection to it (possibly | |
| 608 // through ConnectionManager), then we can make a sync IPC to it here to get | |
| 609 // a token for this handle, and it will duplicate the handle to is process. | |
| 610 // Then we pass the token to the receiver, which will then make a sync call | |
| 611 // to the broker to get a duplicated handle. This will also allow us to | |
| 612 // avoid leaks of the handle if the receiver dies, since the broker can | |
| 613 // notice that. | |
| 614 DCHECK_GT(num_platform_handles, 0u); | 601 DCHECK_GT(num_platform_handles, 0u); |
| 615 ScopedPlatformHandleVectorPtr rv(new PlatformHandleVector()); | 602 ScopedPlatformHandleVectorPtr rv(new PlatformHandleVector()); |
| 603 rv->resize(num_platform_handles); |
| 616 | 604 |
| 617 const SerializedHandle* serialization_data = | 605 const uint64_t* tokens = |
| 618 static_cast<const SerializedHandle*>(platform_handle_table); | 606 static_cast<const uint64_t*>(platform_handle_table); |
| 619 for (size_t i = 0; i < num_platform_handles; i++) { | 607 internal::g_token_serializer->TokenToHandle( |
| 620 DWORD pid = serialization_data->handle_pid; | 608 tokens, num_platform_handles, &rv->at(0)); |
| 621 HANDLE source_handle = serialization_data->handle; | |
| 622 serialization_data ++; | |
| 623 base::Process sender = | |
| 624 base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); | |
| 625 DCHECK(sender.IsValid()); | |
| 626 HANDLE target_handle = NULL; | |
| 627 BOOL dup_result = DuplicateHandle( | |
| 628 sender.Handle(), source_handle, | |
| 629 base::GetCurrentProcessHandle(), &target_handle, 0, | |
| 630 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); | |
| 631 DCHECK(dup_result); | |
| 632 rv->push_back(PlatformHandle(target_handle)); | |
| 633 } | |
| 634 return rv.Pass(); | 609 return rv.Pass(); |
| 635 } | 610 } |
| 636 | 611 |
| 637 size_t SerializePlatformHandles(std::vector<int>* fds) override { | 612 size_t SerializePlatformHandles(std::vector<int>* fds) override { |
| 638 if (!write_buffer_no_lock()->HavePlatformHandlesToSend()) | 613 if (!write_buffer_no_lock()->HavePlatformHandlesToSend()) |
| 639 return 0u; | 614 return 0u; |
| 640 | 615 |
| 641 // Since we're not sure which process might ultimately deserialize this | |
| 642 // message, we can't duplicate the handle now. Instead, write the process | |
| 643 // ID and handle now and let the receiver duplicate it. | |
| 644 PlatformHandle* platform_handles; | 616 PlatformHandle* platform_handles; |
| 645 void* serialization_data_temp; | 617 void* serialization_data_temp; |
| 646 size_t num_platform_handles; | 618 size_t num_platform_handles; |
| 647 write_buffer_no_lock()->GetPlatformHandlesToSend( | 619 write_buffer_no_lock()->GetPlatformHandlesToSend( |
| 648 &num_platform_handles, &platform_handles, &serialization_data_temp); | 620 &num_platform_handles, &platform_handles, &serialization_data_temp); |
| 649 SerializedHandle* serialization_data = | 621 uint64_t* tokens = static_cast<uint64_t*>(serialization_data_temp); |
| 650 static_cast<SerializedHandle*>(serialization_data_temp); | |
| 651 DCHECK_GT(num_platform_handles, 0u); | 622 DCHECK_GT(num_platform_handles, 0u); |
| 652 DCHECK(platform_handles); | 623 DCHECK(platform_handles); |
| 653 | 624 |
| 654 DWORD current_process_id = base::GetCurrentProcId(); | 625 internal::g_token_serializer->HandleToToken( |
| 655 for (size_t i = 0; i < num_platform_handles; i++) { | 626 &platform_handles[0], num_platform_handles, tokens); |
| 656 serialization_data->handle_pid = current_process_id; | 627 for (size_t i = 0; i < num_platform_handles; i++) |
| 657 serialization_data->handle = platform_handles[i].handle; | |
| 658 serialization_data++; | |
| 659 platform_handles[i] = PlatformHandle(); | 628 platform_handles[i] = PlatformHandle(); |
| 660 } | |
| 661 return num_platform_handles; | 629 return num_platform_handles; |
| 662 } | 630 } |
| 663 | 631 |
| 664 IOResult WriteNoLock(size_t* platform_handles_written, | 632 IOResult WriteNoLock(size_t* platform_handles_written, |
| 665 size_t* bytes_written) override { | 633 size_t* bytes_written) override { |
| 666 write_lock().AssertAcquired(); | 634 write_lock().AssertAcquired(); |
| 667 | 635 |
| 668 DCHECK(io_handler_); | 636 DCHECK(io_handler_); |
| 669 DCHECK(!io_handler_->pending_write_no_lock()); | 637 DCHECK(!io_handler_->pending_write_no_lock()); |
| 670 | 638 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 | 739 |
| 772 } // namespace | 740 } // namespace |
| 773 | 741 |
| 774 // ----------------------------------------------------------------------------- | 742 // ----------------------------------------------------------------------------- |
| 775 | 743 |
| 776 RawChannel* RawChannel::Create(ScopedPlatformHandle handle) { | 744 RawChannel* RawChannel::Create(ScopedPlatformHandle handle) { |
| 777 return new RawChannelWin(handle.Pass()); | 745 return new RawChannelWin(handle.Pass()); |
| 778 } | 746 } |
| 779 | 747 |
| 780 size_t RawChannel::GetSerializedPlatformHandleSize() { | 748 size_t RawChannel::GetSerializedPlatformHandleSize() { |
| 781 return sizeof(SerializedHandle); | 749 return sizeof(uint64_t); |
| 782 } | 750 } |
| 783 | 751 |
| 784 bool RawChannel::IsOtherEndOf(RawChannel* other) { | 752 bool RawChannel::IsOtherEndOf(RawChannel* other) { |
| 785 DCHECK_NE(other, this); | 753 DCHECK_NE(other, this); |
| 786 PlatformHandle this_handle = static_cast<RawChannelWin*>(this)->GetHandle(); | 754 PlatformHandle this_handle = static_cast<RawChannelWin*>(this)->GetHandle(); |
| 787 PlatformHandle other_handle = static_cast<RawChannelWin*>(other)->GetHandle(); | 755 PlatformHandle other_handle = static_cast<RawChannelWin*>(other)->GetHandle(); |
| 788 | 756 |
| 789 if (g_vista_or_higher_functions.Get().is_vista_or_higher()) { | 757 if (g_vista_or_higher_functions.Get().is_vista_or_higher()) { |
| 790 WCHAR data1[_MAX_PATH + sizeof(FILE_NAME_INFO)]; | 758 WCHAR data1[_MAX_PATH + sizeof(FILE_NAME_INFO)]; |
| 791 WCHAR data2[_MAX_PATH + sizeof(FILE_NAME_INFO)]; | 759 WCHAR data2[_MAX_PATH + sizeof(FILE_NAME_INFO)]; |
| 792 FILE_NAME_INFO* fileinfo1 = reinterpret_cast<FILE_NAME_INFO *>(data1); | 760 FILE_NAME_INFO* fileinfo1 = reinterpret_cast<FILE_NAME_INFO *>(data1); |
| 793 FILE_NAME_INFO* fileinfo2 = reinterpret_cast<FILE_NAME_INFO *>(data2); | 761 FILE_NAME_INFO* fileinfo2 = reinterpret_cast<FILE_NAME_INFO *>(data2); |
| 794 CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx( | 762 CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx( |
| 795 this_handle.handle, FileNameInfo, fileinfo1, arraysize(data1))); | 763 this_handle.handle, FileNameInfo, fileinfo1, arraysize(data1))); |
| 796 CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx( | 764 CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx( |
| 797 other_handle.handle, FileNameInfo, fileinfo2, arraysize(data2))); | 765 other_handle.handle, FileNameInfo, fileinfo2, arraysize(data2))); |
| 798 std::wstring filepath1(fileinfo1->FileName, fileinfo1->FileNameLength / 2); | 766 std::wstring filepath1(fileinfo1->FileName, fileinfo1->FileNameLength / 2); |
| 799 std::wstring filepath2(fileinfo2->FileName, fileinfo2->FileNameLength / 2); | 767 std::wstring filepath2(fileinfo2->FileName, fileinfo2->FileNameLength / 2); |
| 800 return filepath1 == filepath2; | 768 return filepath1 == filepath2; |
| 801 } else { | 769 } else { |
| 802 // This is to catch developer errors. Let them be caught on Vista and above, | 770 // This is to catch developer errors. Let them be caught on Vista and above, |
| 803 // i.e. no point in implementing this on XP since support for it will be | 771 // i.e. no point in implementing this on XP since support for it will be |
| 804 // removed in early 2016. | 772 // removed in early 2016. |
| 805 return false; | 773 return false; |
| 806 } | 774 } |
| 807 } | 775 } |
| 808 | 776 |
| 809 } // namespace edk | 777 } // namespace edk |
| 810 } // namespace mojo | 778 } // namespace mojo |
| OLD | NEW |