OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/channel.h" | 5 #include "mojo/edk/system/channel.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <limits> | 10 #include <limits> |
| 11 #include <utility> |
11 | 12 |
12 #include "base/macros.h" | 13 #include "base/macros.h" |
13 #include "base/memory/aligned_memory.h" | 14 #include "base/memory/aligned_memory.h" |
14 #include "mojo/edk/embedder/platform_handle.h" | 15 #include "mojo/edk/embedder/platform_handle.h" |
15 | 16 |
| 17 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 18 #include "base/mac/mach_logging.h" |
| 19 #endif |
| 20 |
16 namespace mojo { | 21 namespace mojo { |
17 namespace edk { | 22 namespace edk { |
18 | 23 |
19 namespace { | 24 namespace { |
20 | 25 |
21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, | 26 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, |
22 "Invalid Header size."); | 27 "Invalid Header size."); |
23 | 28 |
24 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 29 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
25 static_assert(sizeof(Channel::Message::Header) == 8, | 30 static_assert(sizeof(Channel::Message::Header) == 8, |
(...skipping 10 matching lines...) Expand all Loading... |
36 Channel::Message::Message(size_t payload_size, | 41 Channel::Message::Message(size_t payload_size, |
37 size_t max_handles, | 42 size_t max_handles, |
38 Header::MessageType message_type) | 43 Header::MessageType message_type) |
39 : max_handles_(max_handles) { | 44 : max_handles_(max_handles) { |
40 DCHECK_LE(max_handles_, kMaxAttachedHandles); | 45 DCHECK_LE(max_handles_, kMaxAttachedHandles); |
41 | 46 |
42 size_t extra_header_size = 0; | 47 size_t extra_header_size = 0; |
43 #if defined(OS_WIN) | 48 #if defined(OS_WIN) |
44 // On Windows we serialize platform handles into the extra header space. | 49 // On Windows we serialize platform handles into the extra header space. |
45 extra_header_size = max_handles_ * sizeof(PlatformHandle); | 50 extra_header_size = max_handles_ * sizeof(PlatformHandle); |
| 51 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 52 // On OSX, some of the platform handles may be mach ports, which are |
| 53 // serialised into the message buffer. Since there could be a mix of fds and |
| 54 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), |
| 55 // so that the original ordering of handles can be re-created. |
| 56 extra_header_size = max_handles * sizeof(MachPortsEntry); |
46 #endif | 57 #endif |
47 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. | 58 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. |
48 if (extra_header_size % kChannelMessageAlignment) { | 59 if (extra_header_size % kChannelMessageAlignment) { |
49 extra_header_size += kChannelMessageAlignment - | 60 extra_header_size += kChannelMessageAlignment - |
50 (extra_header_size % kChannelMessageAlignment); | 61 (extra_header_size % kChannelMessageAlignment); |
51 } | 62 } |
52 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); | 63 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); |
53 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 64 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
54 DCHECK_EQ(0u, extra_header_size); | 65 DCHECK_EQ(0u, extra_header_size); |
55 #endif | 66 #endif |
(...skipping 15 matching lines...) Expand all Loading... |
71 DCHECK_LE(sizeof(Header) + extra_header_size, | 82 DCHECK_LE(sizeof(Header) + extra_header_size, |
72 std::numeric_limits<uint16_t>::max()); | 83 std::numeric_limits<uint16_t>::max()); |
73 header_->message_type = message_type; | 84 header_->message_type = message_type; |
74 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 85 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
75 header_->num_handles = static_cast<uint16_t>(max_handles); | 86 header_->num_handles = static_cast<uint16_t>(max_handles); |
76 #else | 87 #else |
77 header_->num_header_bytes = | 88 header_->num_header_bytes = |
78 static_cast<uint16_t>(sizeof(Header) + extra_header_size); | 89 static_cast<uint16_t>(sizeof(Header) + extra_header_size); |
79 #endif | 90 #endif |
80 | 91 |
| 92 if (max_handles_ > 0) { |
81 #if defined(OS_WIN) | 93 #if defined(OS_WIN) |
82 if (max_handles_ > 0) { | |
83 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); | 94 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); |
84 // Initialize all handles to invalid values. | 95 // Initialize all handles to invalid values. |
85 for (size_t i = 0; i < max_handles_; ++i) | 96 for (size_t i = 0; i < max_handles_; ++i) |
86 handles()[i] = PlatformHandle(); | 97 handles()[i] = PlatformHandle(); |
| 98 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 99 mach_ports_ = reinterpret_cast<MachPortsEntry*>(mutable_extra_header()); |
| 100 // Initialize all handles to invalid values. |
| 101 for (size_t i = 0; i < max_handles_; ++i) |
| 102 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 103 #endif |
87 } | 104 } |
88 #endif | |
89 } | 105 } |
90 | 106 |
91 Channel::Message::~Message() { | 107 Channel::Message::~Message() { |
92 #if defined(OS_WIN) | 108 #if defined(OS_WIN) |
93 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. | 109 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. |
94 for (size_t i = 0; i < header_->num_handles; ++i) | 110 for (size_t i = 0; i < header_->num_handles; ++i) |
95 handles()[i].CloseIfNecessary(); | 111 handles()[i].CloseIfNecessary(); |
96 #endif | 112 #endif |
97 base::AlignedFree(data_); | 113 base::AlignedFree(data_); |
98 } | 114 } |
99 | 115 |
100 // static | 116 // static |
101 Channel::MessagePtr Channel::Message::Deserialize(const void* data, | 117 Channel::MessagePtr Channel::Message::Deserialize(const void* data, |
102 size_t data_num_bytes) { | 118 size_t data_num_bytes) { |
103 #if !defined(OS_WIN) | 119 #if !defined(OS_WIN) && !(defined(OS_MACOSX) && !defined(OS_IOS)) |
104 // We only serialize messages into other messages when performing message | 120 // We only serialize messages into other messages when performing message |
105 // relay on Windows. | 121 // relay on Windows and OSX. |
106 NOTREACHED(); | 122 NOTREACHED(); |
107 return nullptr; | 123 return nullptr; |
108 #else | 124 #else |
109 if (data_num_bytes < sizeof(Header)) | 125 if (data_num_bytes < sizeof(Header)) |
110 return nullptr; | 126 return nullptr; |
111 | 127 |
112 const Header* header = reinterpret_cast<const Header*>(data); | 128 const Header* header = reinterpret_cast<const Header*>(data); |
113 if (header->num_bytes != data_num_bytes) { | 129 if (header->num_bytes != data_num_bytes) { |
114 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes | 130 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes |
115 << " != " << data_num_bytes; | 131 << " != " << data_num_bytes; |
116 return nullptr; | 132 return nullptr; |
117 } | 133 } |
118 | 134 |
119 if (header->num_bytes < header->num_header_bytes) { | 135 if (header->num_bytes < header->num_header_bytes) { |
120 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " | 136 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " |
121 << header->num_header_bytes; | 137 << header->num_header_bytes; |
122 return nullptr; | 138 return nullptr; |
123 } | 139 } |
124 | 140 |
125 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); | 141 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); |
| 142 #if defined(OS_WIN) |
126 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); | 143 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); |
| 144 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 145 uint32_t max_handles = extra_header_size / sizeof(MachPortsEntry); |
| 146 #endif |
127 if (header->num_handles > max_handles) { | 147 if (header->num_handles > max_handles) { |
128 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > " | 148 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles |
129 << max_handles; | 149 << " > " << max_handles; |
130 return nullptr; | 150 return nullptr; |
131 } | 151 } |
132 | 152 |
133 MessagePtr message( | 153 MessagePtr message(new Message(data_num_bytes - header->num_header_bytes, |
134 new Message(data_num_bytes - header->num_header_bytes, max_handles)); | 154 max_handles)); |
135 | |
136 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); | 155 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); |
137 DCHECK_EQ(message->extra_header_size(), extra_header_size); | 156 DCHECK_EQ(message->extra_header_size(), extra_header_size); |
138 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); | 157 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); |
139 | 158 |
140 // Copy all payload bytes. | 159 // Copy all payload bytes. |
141 memcpy(message->mutable_payload(), | 160 memcpy(message->mutable_payload(), |
142 static_cast<const char*>(data) + header->num_header_bytes, | 161 static_cast<const char*>(data) + header->num_header_bytes, |
143 data_num_bytes - header->num_header_bytes); | 162 data_num_bytes - header->num_header_bytes); |
144 // Copy extra header bytes. | 163 // Copy extra header bytes. |
145 memcpy(message->mutable_extra_header(), | 164 memcpy(message->mutable_extra_header(), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 #endif // defined(OS_WIN) | 196 #endif // defined(OS_WIN) |
178 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) | 197 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
179 } | 198 } |
180 | 199 |
181 #if defined(OS_MACOSX) && !defined(OS_IOS) | 200 #if defined(OS_MACOSX) && !defined(OS_IOS) |
182 bool Channel::Message::has_mach_ports() const { | 201 bool Channel::Message::has_mach_ports() const { |
183 if (!has_handles()) | 202 if (!has_handles()) |
184 return false; | 203 return false; |
185 | 204 |
186 for (const auto& handle : (*handle_vector_)) { | 205 for (const auto& handle : (*handle_vector_)) { |
187 if (handle.type == PlatformHandle::Type::MACH) | 206 if (handle.type == PlatformHandle::Type::MACH || |
| 207 handle.type == PlatformHandle::Type::MACH_NAME) { |
188 return true; | 208 return true; |
| 209 } |
189 } | 210 } |
190 return false; | 211 return false; |
191 } | 212 } |
192 #endif | 213 #endif |
193 | 214 |
194 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { | 215 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { |
195 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 216 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
196 // Old semantics for ChromeOS and Android | 217 // Old semantics for ChromeOS and Android |
197 if (header_->num_handles == 0) { | 218 if (header_->num_handles == 0) { |
198 CHECK(!new_handles || new_handles->size() == 0); | 219 CHECK(!new_handles || new_handles->size() == 0); |
(...skipping 11 matching lines...) Expand all Loading... |
210 CHECK(new_handles && new_handles->size() <= max_handles_); | 231 CHECK(new_handles && new_handles->size() <= max_handles_); |
211 header_->num_handles = static_cast<uint16_t>(new_handles->size()); | 232 header_->num_handles = static_cast<uint16_t>(new_handles->size()); |
212 #if defined(OS_WIN) | 233 #if defined(OS_WIN) |
213 memcpy(handles(), new_handles->data(), | 234 memcpy(handles(), new_handles->data(), |
214 sizeof(PlatformHandle) * new_handles->size()); | 235 sizeof(PlatformHandle) * new_handles->size()); |
215 new_handles->clear(); | 236 new_handles->clear(); |
216 #else | 237 #else |
217 std::swap(handle_vector_, new_handles); | 238 std::swap(handle_vector_, new_handles); |
218 #endif // defined(OS_WIN) | 239 #endif // defined(OS_WIN) |
219 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) | 240 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 241 |
| 242 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 243 size_t mach_port_index = 0; |
| 244 for (size_t i = 0; i < max_handles_; ++i) |
| 245 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 246 for (size_t i = 0; i < handle_vector_->size(); i++) { |
| 247 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || |
| 248 (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { |
| 249 mach_port_t port = (*handle_vector_)[i].port; |
| 250 mach_ports_[mach_port_index].index = i; |
| 251 mach_ports_[mach_port_index].mach_port = port; |
| 252 mach_port_index++; |
| 253 } |
| 254 } |
| 255 #endif |
220 } | 256 } |
221 | 257 |
222 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { | 258 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { |
223 #if defined(OS_WIN) | 259 #if defined(OS_WIN) |
224 if (header_->num_handles == 0) | 260 if (header_->num_handles == 0) |
225 return ScopedPlatformHandleVectorPtr(); | 261 return ScopedPlatformHandleVectorPtr(); |
226 ScopedPlatformHandleVectorPtr moved_handles( | 262 ScopedPlatformHandleVectorPtr moved_handles( |
227 new PlatformHandleVector(header_->num_handles)); | 263 new PlatformHandleVector(header_->num_handles)); |
228 for (size_t i = 0; i < header_->num_handles; ++i) | 264 for (size_t i = 0; i < header_->num_handles; ++i) |
229 std::swap(moved_handles->at(i), handles()[i]); | 265 std::swap(moved_handles->at(i), handles()[i]); |
| 266 header_->num_handles = 0; |
230 return moved_handles; | 267 return moved_handles; |
| 268 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 269 for (size_t i = 0; i < max_handles_; ++i) |
| 270 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 271 header_->num_handles = 0; |
| 272 return std::move(handle_vector_); |
| 273 #else |
| 274 header_->num_handles = 0; |
| 275 return std::move(handle_vector_); |
| 276 #endif |
| 277 } |
| 278 |
| 279 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { |
| 280 #if defined(OS_WIN) |
| 281 // Not necessary on Windows. |
| 282 NOTREACHED(); |
| 283 return nullptr; |
| 284 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 285 if (handle_vector_) { |
| 286 for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { |
| 287 if (it->type == PlatformHandle::Type::MACH || |
| 288 it->type == PlatformHandle::Type::MACH_NAME) { |
| 289 // For Mach port names, we can can just leak them. They're not real |
| 290 // ports anyways. For real ports, they're leaked because this is a child |
| 291 // process and the remote process will take ownership. |
| 292 it = handle_vector_->erase(it); |
| 293 } else { |
| 294 ++it; |
| 295 } |
| 296 } |
| 297 } |
| 298 return std::move(handle_vector_); |
231 #else | 299 #else |
232 return std::move(handle_vector_); | 300 return std::move(handle_vector_); |
233 #endif | 301 #endif |
234 } | 302 } |
235 | 303 |
236 #if defined(OS_WIN) | 304 #if defined(OS_WIN) |
237 // static | 305 // static |
238 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, | 306 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, |
239 base::ProcessHandle to_process, | 307 base::ProcessHandle to_process, |
240 PlatformHandle* handles, | 308 PlatformHandle* handles, |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 return true; | 515 return true; |
448 } | 516 } |
449 | 517 |
450 void Channel::OnError() { | 518 void Channel::OnError() { |
451 if (delegate_) | 519 if (delegate_) |
452 delegate_->OnChannelError(); | 520 delegate_->OnChannelError(); |
453 } | 521 } |
454 | 522 |
455 } // namespace edk | 523 } // namespace edk |
456 } // namespace mojo | 524 } // namespace mojo |
OLD | NEW |