• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
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 "ipc/ipc_message_attachment.h"
6 
7 #include "base/files/scoped_file.h"
8 #include "base/logging.h"
9 #include "base/notreached.h"
10 #include "build/build_config.h"
11 #include "ipc/ipc_mojo_handle_attachment.h"
12 #include "mojo/public/cpp/system/platform_handle.h"
13 
14 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
15 #include <unistd.h>
16 
17 #include "base/posix/eintr_wrapper.h"
18 #include "ipc/ipc_platform_file_attachment_posix.h"
19 #endif
20 
21 #if BUILDFLAG(IS_MAC)
22 #include "ipc/mach_port_attachment_mac.h"
23 #endif
24 
25 #if BUILDFLAG(IS_WIN)
26 #include "ipc/handle_attachment_win.h"
27 #endif
28 
29 #if BUILDFLAG(IS_FUCHSIA)
30 #include "ipc/handle_attachment_fuchsia.h"
31 #endif
32 
33 namespace IPC {
34 
35 namespace {
36 
37 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TakeOrDupFile(internal::PlatformFileAttachment * attachment)38 base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
39   return attachment->Owns()
40              ? base::ScopedFD(attachment->TakePlatformFile())
41              : base::ScopedFD(HANDLE_EINTR(dup(attachment->file())));
42 }
43 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
44 
45 }  // namespace
46 
47 MessageAttachment::MessageAttachment() = default;
48 
49 MessageAttachment::~MessageAttachment() = default;
50 
TakeMojoHandle()51 mojo::ScopedHandle MessageAttachment::TakeMojoHandle() {
52   switch (GetType()) {
53     case Type::MOJO_HANDLE:
54       return static_cast<internal::MojoHandleAttachment*>(this)->TakeHandle();
55 
56 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
57     case Type::PLATFORM_FILE: {
58       // We dup() the handles in IPC::Message to transmit.
59       // IPC::MessageAttachmentSet has intricate lifetime semantics for FDs, so
60       // just to dup()-and-own them is the safest option.
61       base::ScopedFD file =
62           TakeOrDupFile(static_cast<internal::PlatformFileAttachment*>(this));
63       if (!file.is_valid()) {
64         DPLOG(WARNING) << "Failed to dup FD to transmit.";
65         return mojo::ScopedHandle();
66       }
67       return mojo::WrapPlatformFile(std::move(file));
68     }
69 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
70 
71 #if BUILDFLAG(IS_MAC)
72     case Type::MACH_PORT: {
73       auto* attachment = static_cast<internal::MachPortAttachmentMac*>(this);
74       MojoPlatformHandle platform_handle = {
75           sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT,
76           static_cast<uint64_t>(attachment->get_mach_port())};
77       MojoHandle wrapped_handle;
78       if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
79           MOJO_RESULT_OK) {
80         return mojo::ScopedHandle();
81       }
82       attachment->reset_mach_port_ownership();
83       return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
84     }
85 #elif BUILDFLAG(IS_FUCHSIA)
86     case Type::FUCHSIA_HANDLE: {
87       auto* attachment = static_cast<internal::HandleAttachmentFuchsia*>(this);
88       MojoPlatformHandle platform_handle = {
89           sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE,
90           static_cast<uint64_t>(attachment->Take())};
91       MojoHandle wrapped_handle;
92       if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
93           MOJO_RESULT_OK) {
94         return mojo::ScopedHandle();
95       }
96       return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
97     }
98 #elif BUILDFLAG(IS_WIN)
99     case Type::WIN_HANDLE:
100       return mojo::WrapPlatformFile(base::win::ScopedHandle(
101           static_cast<internal::HandleAttachmentWin*>(this)->Take()));
102 #endif
103     default:
104       break;
105   }
106   NOTREACHED();
107 }
108 
109 // static
CreateFromMojoHandle(mojo::ScopedHandle handle,Type type)110 scoped_refptr<MessageAttachment> MessageAttachment::CreateFromMojoHandle(
111     mojo::ScopedHandle handle,
112     Type type) {
113   if (type == Type::MOJO_HANDLE)
114     return new internal::MojoHandleAttachment(std::move(handle));
115 
116   MojoPlatformHandle platform_handle = {sizeof(platform_handle), 0, 0};
117   MojoResult unwrap_result = MojoUnwrapPlatformHandle(
118       handle.release().value(), nullptr, &platform_handle);
119   if (unwrap_result != MOJO_RESULT_OK)
120     return nullptr;
121 
122 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
123   if (type == Type::PLATFORM_FILE) {
124     base::PlatformFile file = base::kInvalidPlatformFile;
125     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
126       file = static_cast<base::PlatformFile>(platform_handle.value);
127     return new internal::PlatformFileAttachment(file);
128   }
129 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
130 
131 #if BUILDFLAG(IS_MAC)
132   if (type == Type::MACH_PORT) {
133     mach_port_t mach_port = MACH_PORT_NULL;
134     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
135       mach_port = static_cast<mach_port_t>(platform_handle.value);
136     return new internal::MachPortAttachmentMac(
137         mach_port, internal::MachPortAttachmentMac::FROM_WIRE);
138   }
139 #elif BUILDFLAG(IS_FUCHSIA)
140   if (type == Type::FUCHSIA_HANDLE) {
141     zx::handle zx_handle;
142     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
143       zx_handle.reset(static_cast<zx_handle_t>(platform_handle.value));
144     return new internal::HandleAttachmentFuchsia(std::move(zx_handle));
145   }
146 #elif BUILDFLAG(IS_WIN)
147   if (type == Type::WIN_HANDLE) {
148     base::PlatformFile platform_file = base::kInvalidPlatformFile;
149     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) {
150       platform_file =
151           reinterpret_cast<base::PlatformFile>(platform_handle.value);
152     }
153     return new internal::HandleAttachmentWin(
154         platform_file, internal::HandleAttachmentWin::FROM_WIRE);
155   }
156 #endif
157   NOTREACHED();
158 }
159 
160 }  // namespace IPC
161