| 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 |