... |
... |
@@ -30,6 +30,34 @@ |
30
|
30
|
|
31
|
31
|
using namespace mozilla::ipc;
|
32
|
32
|
|
|
33
|
+namespace {
|
|
34
|
+
|
|
35
|
+// This logic is borrowed from Chromium's `base/win/win_util.h`. It allows us
|
|
36
|
+// to distinguish pseudo-handle values, such as returned by GetCurrentProcess()
|
|
37
|
+// (-1), GetCurrentThread() (-2), and potentially more. The code there claims
|
|
38
|
+// that fuzzers have found issues up until -12 with DuplicateHandle.
|
|
39
|
+//
|
|
40
|
+// https://source.chromium.org/chromium/chromium/src/+/36dbbf38697dd1e23ef8944bb9e57f6e0b3d41ec:base/win/win_util.h
|
|
41
|
+inline bool IsPseudoHandle(HANDLE handle) {
|
|
42
|
+ auto handleValue = static_cast<int32_t>(reinterpret_cast<uintptr_t>(handle));
|
|
43
|
+ return -12 <= handleValue && handleValue < 0;
|
|
44
|
+}
|
|
45
|
+
|
|
46
|
+// A real handle is a handle that is not a pseudo-handle. Always preferably use
|
|
47
|
+// this variant over ::DuplicateHandle. Only use stock ::DuplicateHandle if you
|
|
48
|
+// explicitly need the ability to duplicate a pseudo-handle.
|
|
49
|
+inline bool DuplicateRealHandle(HANDLE source_process, HANDLE source_handle,
|
|
50
|
+ HANDLE target_process, LPHANDLE target_handle,
|
|
51
|
+ DWORD desired_access, BOOL inherit_handle,
|
|
52
|
+ DWORD options) {
|
|
53
|
+ MOZ_RELEASE_ASSERT(!IsPseudoHandle(source_handle));
|
|
54
|
+ return static_cast<bool>(::DuplicateHandle(
|
|
55
|
+ source_process, source_handle, target_process, target_handle,
|
|
56
|
+ desired_access, inherit_handle, options));
|
|
57
|
+}
|
|
58
|
+
|
|
59
|
+} // namespace
|
|
60
|
+
|
33
|
61
|
namespace IPC {
|
34
|
62
|
//------------------------------------------------------------------------------
|
35
|
63
|
|
... |
... |
@@ -595,7 +623,7 @@ bool Channel::ChannelImpl::AcceptHandles(Message& msg) { |
595
|
623
|
nsTArray<mozilla::UniqueFileHandle> handles(num_handles);
|
596
|
624
|
for (uint32_t handleValue : payload) {
|
597
|
625
|
HANDLE ipc_handle = Uint32ToHandle(handleValue);
|
598
|
|
- if (!ipc_handle || ipc_handle == INVALID_HANDLE_VALUE) {
|
|
626
|
+ if (!ipc_handle || IsPseudoHandle(ipc_handle)) {
|
599
|
627
|
CHROMIUM_LOG(ERROR)
|
600
|
628
|
<< "Attempt to accept invalid or null handle from process "
|
601
|
629
|
<< other_pid_ << " for message " << msg.name() << " in AcceptHandles";
|
... |
... |
@@ -613,9 +641,10 @@ bool Channel::ChannelImpl::AcceptHandles(Message& msg) { |
613
|
641
|
CHROMIUM_LOG(ERROR) << "other_process_ is invalid in AcceptHandles";
|
614
|
642
|
return false;
|
615
|
643
|
}
|
616
|
|
- if (!::DuplicateHandle(other_process_, ipc_handle, GetCurrentProcess(),
|
617
|
|
- getter_Transfers(local_handle), 0, FALSE,
|
618
|
|
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) {
|
|
644
|
+ if (!DuplicateRealHandle(
|
|
645
|
+ other_process_, ipc_handle, GetCurrentProcess(),
|
|
646
|
+ getter_Transfers(local_handle), 0, FALSE,
|
|
647
|
+ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) {
|
619
|
648
|
DWORD err = GetLastError();
|
620
|
649
|
// Don't log out a scary looking error if this failed due to the target
|
621
|
650
|
// process terminating.
|
... |
... |
@@ -688,9 +717,9 @@ bool Channel::ChannelImpl::TransferHandles(Message& msg) { |
688
|
717
|
CHROMIUM_LOG(ERROR) << "other_process_ is invalid in TransferHandles";
|
689
|
718
|
return false;
|
690
|
719
|
}
|
691
|
|
- if (!::DuplicateHandle(GetCurrentProcess(), local_handle.get(),
|
692
|
|
- other_process_, &ipc_handle, 0, FALSE,
|
693
|
|
- DUPLICATE_SAME_ACCESS)) {
|
|
720
|
+ if (!DuplicateRealHandle(GetCurrentProcess(), local_handle.get(),
|
|
721
|
+ other_process_, &ipc_handle, 0, FALSE,
|
|
722
|
+ DUPLICATE_SAME_ACCESS)) {
|
694
|
723
|
DWORD err = GetLastError();
|
695
|
724
|
// Don't log out a scary looking error if this failed due to the target
|
696
|
725
|
// process terminating.
|