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 |