| 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 #include <utility> |
| 12 | 12 |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/aligned_memory.h" | 14 #include "base/memory/aligned_memory.h" |
| 15 #include "base/process/process_handle.h" | 15 #include "base/process/process_handle.h" |
| 16 #include "mojo/edk/embedder/platform_handle.h" | 16 #include "mojo/edk/embedder/platform_handle.h" |
| 17 | 17 |
| 18 #if defined(OS_MACOSX) && !defined(OS_IOS) | 18 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 19 #include "base/mac/mach_logging.h" | 19 #include "base/mac/mach_logging.h" |
| 20 #elif defined(OS_WIN) |
| 21 #include "base/win/win_util.h" |
| 20 #endif | 22 #endif |
| 21 | 23 |
| 22 namespace mojo { | 24 namespace mojo { |
| 23 namespace edk { | 25 namespace edk { |
| 24 | 26 |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 27 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, | 29 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, |
| 28 "Invalid Header size."); | 30 "Invalid Header size."); |
| 29 | 31 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 40 const size_t kMaxAttachedHandles = 128; | 42 const size_t kMaxAttachedHandles = 128; |
| 41 | 43 |
| 42 Channel::Message::Message(size_t payload_size, | 44 Channel::Message::Message(size_t payload_size, |
| 43 size_t max_handles, | 45 size_t max_handles, |
| 44 Header::MessageType message_type) | 46 Header::MessageType message_type) |
| 45 : max_handles_(max_handles) { | 47 : max_handles_(max_handles) { |
| 46 DCHECK_LE(max_handles_, kMaxAttachedHandles); | 48 DCHECK_LE(max_handles_, kMaxAttachedHandles); |
| 47 | 49 |
| 48 size_t extra_header_size = 0; | 50 size_t extra_header_size = 0; |
| 49 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
| 50 // On Windows we serialize platform handles into the extra header space. | 52 // On Windows we serialize HANDLEs into the extra header space. |
| 51 extra_header_size = max_handles_ * sizeof(PlatformHandle); | 53 extra_header_size = max_handles_ * sizeof(HandleEntry); |
| 52 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 54 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 53 // On OSX, some of the platform handles may be mach ports, which are | 55 // On OSX, some of the platform handles may be mach ports, which are |
| 54 // serialised into the message buffer. Since there could be a mix of fds and | 56 // serialised into the message buffer. Since there could be a mix of fds and |
| 55 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), | 57 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), |
| 56 // so that the original ordering of handles can be re-created. | 58 // so that the original ordering of handles can be re-created. |
| 57 if (max_handles) { | 59 if (max_handles) { |
| 58 extra_header_size = | 60 extra_header_size = |
| 59 sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); | 61 sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); |
| 60 } | 62 } |
| 61 #endif | 63 #endif |
| (...skipping 26 matching lines...) Expand all Loading... |
| 88 header_->message_type = message_type; | 90 header_->message_type = message_type; |
| 89 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 91 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 90 header_->num_handles = static_cast<uint16_t>(max_handles); | 92 header_->num_handles = static_cast<uint16_t>(max_handles); |
| 91 #else | 93 #else |
| 92 header_->num_header_bytes = | 94 header_->num_header_bytes = |
| 93 static_cast<uint16_t>(sizeof(Header) + extra_header_size); | 95 static_cast<uint16_t>(sizeof(Header) + extra_header_size); |
| 94 #endif | 96 #endif |
| 95 | 97 |
| 96 if (max_handles_ > 0) { | 98 if (max_handles_ > 0) { |
| 97 #if defined(OS_WIN) | 99 #if defined(OS_WIN) |
| 98 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); | 100 handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header()); |
| 99 // Initialize all handles to invalid values. | 101 // Initialize all handles to invalid values. |
| 100 for (size_t i = 0; i < max_handles_; ++i) | 102 for (size_t i = 0; i < max_handles_; ++i) |
| 101 handles()[i] = PlatformHandle(); | 103 handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE); |
| 102 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 104 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 103 mach_ports_header_ = | 105 mach_ports_header_ = |
| 104 reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); | 106 reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); |
| 105 mach_ports_header_->num_ports = 0; | 107 mach_ports_header_->num_ports = 0; |
| 106 // Initialize all handles to invalid values. | 108 // Initialize all handles to invalid values. |
| 107 for (size_t i = 0; i < max_handles_; ++i) { | 109 for (size_t i = 0; i < max_handles_; ++i) { |
| 108 mach_ports_header_->entries[i] = | 110 mach_ports_header_->entries[i] = |
| 109 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 111 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 110 } | 112 } |
| 111 #endif | 113 #endif |
| 112 } | 114 } |
| 113 } | 115 } |
| 114 | 116 |
| 115 Channel::Message::~Message() { | 117 Channel::Message::~Message() { |
| 116 #if defined(OS_WIN) | |
| 117 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. | |
| 118 for (size_t i = 0; i < header_->num_handles; ++i) | |
| 119 handles()[i].CloseIfNecessary(); | |
| 120 #endif | |
| 121 base::AlignedFree(data_); | 118 base::AlignedFree(data_); |
| 122 } | 119 } |
| 123 | 120 |
| 124 // static | 121 // static |
| 125 Channel::MessagePtr Channel::Message::Deserialize(const void* data, | 122 Channel::MessagePtr Channel::Message::Deserialize(const void* data, |
| 126 size_t data_num_bytes) { | 123 size_t data_num_bytes) { |
| 127 #if !defined(OS_WIN) && !(defined(OS_MACOSX) && !defined(OS_IOS)) | 124 #if !defined(OS_WIN) && !(defined(OS_MACOSX) && !defined(OS_IOS)) |
| 128 // We only serialize messages into other messages when performing message | 125 // We only serialize messages into other messages when performing message |
| 129 // relay on Windows and OSX. | 126 // relay on Windows and OSX. |
| 130 NOTREACHED(); | 127 NOTREACHED(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 141 } | 138 } |
| 142 | 139 |
| 143 if (header->num_bytes < header->num_header_bytes) { | 140 if (header->num_bytes < header->num_header_bytes) { |
| 144 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " | 141 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " |
| 145 << header->num_header_bytes; | 142 << header->num_header_bytes; |
| 146 return nullptr; | 143 return nullptr; |
| 147 } | 144 } |
| 148 | 145 |
| 149 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); | 146 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); |
| 150 #if defined(OS_WIN) | 147 #if defined(OS_WIN) |
| 151 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); | 148 uint32_t max_handles = extra_header_size / sizeof(HandleEntry); |
| 152 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 149 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 153 uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) / | 150 uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) / |
| 154 sizeof(MachPortsEntry); | 151 sizeof(MachPortsEntry); |
| 155 #endif | 152 #endif |
| 156 if (header->num_handles > max_handles) { | 153 if (header->num_handles > max_handles) { |
| 157 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles | 154 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles |
| 158 << " > " << max_handles; | 155 << " > " << max_handles; |
| 159 return nullptr; | 156 return nullptr; |
| 160 } | 157 } |
| 161 | 158 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 173 } | 170 } |
| 174 | 171 |
| 175 if (message->extra_header_size()) { | 172 if (message->extra_header_size()) { |
| 176 // Copy extra header bytes. | 173 // Copy extra header bytes. |
| 177 memcpy(message->mutable_extra_header(), | 174 memcpy(message->mutable_extra_header(), |
| 178 static_cast<const char*>(data) + sizeof(Header), | 175 static_cast<const char*>(data) + sizeof(Header), |
| 179 message->extra_header_size()); | 176 message->extra_header_size()); |
| 180 } | 177 } |
| 181 | 178 |
| 182 message->header_->num_handles = header->num_handles; | 179 message->header_->num_handles = header->num_handles; |
| 180 #if defined(OS_WIN) |
| 181 ScopedPlatformHandleVectorPtr handles( |
| 182 new PlatformHandleVector(header->num_handles)); |
| 183 for (size_t i = 0; i < header->num_handles; i++) { |
| 184 (*handles)[i].handle = reinterpret_cast<HANDLE>( |
| 185 static_cast<uintptr_t>(message->handles_[i].handle)); |
| 186 } |
| 187 message->SetHandles(std::move(handles)); |
| 188 #endif |
| 183 | 189 |
| 184 return message; | 190 return message; |
| 185 #endif | 191 #endif |
| 186 } | 192 } |
| 187 | 193 |
| 188 size_t Channel::Message::payload_size() const { | 194 size_t Channel::Message::payload_size() const { |
| 189 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 195 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 190 return header_->num_bytes - sizeof(Header); | 196 return header_->num_bytes - sizeof(Header); |
| 191 #else | 197 #else |
| 192 return size_ - header_->num_header_bytes; | 198 return size_ - header_->num_header_bytes; |
| 193 #endif | 199 #endif |
| 194 } | 200 } |
| 195 | 201 |
| 196 PlatformHandle* Channel::Message::handles() { | |
| 197 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | |
| 198 // Old semantics for ChromeOS and Android. | |
| 199 if (header_->num_handles == 0) | |
| 200 return nullptr; | |
| 201 CHECK(handle_vector_); | |
| 202 return handle_vector_->data(); | |
| 203 #else | |
| 204 if (max_handles_ == 0) | |
| 205 return nullptr; | |
| 206 #if defined(OS_WIN) | |
| 207 return handles_; | |
| 208 #else | |
| 209 CHECK(handle_vector_); | |
| 210 return handle_vector_->data(); | |
| 211 #endif // defined(OS_WIN) | |
| 212 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) | |
| 213 } | |
| 214 | |
| 215 #if defined(OS_MACOSX) && !defined(OS_IOS) | 202 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 216 bool Channel::Message::has_mach_ports() const { | 203 bool Channel::Message::has_mach_ports() const { |
| 217 if (!has_handles()) | 204 if (!has_handles()) |
| 218 return false; | 205 return false; |
| 219 | 206 |
| 220 for (const auto& handle : (*handle_vector_)) { | 207 for (const auto& handle : (*handle_vector_)) { |
| 221 if (handle.type == PlatformHandle::Type::MACH || | 208 if (handle.type == PlatformHandle::Type::MACH || |
| 222 handle.type == PlatformHandle::Type::MACH_NAME) { | 209 handle.type == PlatformHandle::Type::MACH_NAME) { |
| 223 return true; | 210 return true; |
| 224 } | 211 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 238 std::swap(handle_vector_, new_handles); | 225 std::swap(handle_vector_, new_handles); |
| 239 | 226 |
| 240 #else | 227 #else |
| 241 if (max_handles_ == 0) { | 228 if (max_handles_ == 0) { |
| 242 CHECK(!new_handles || new_handles->size() == 0); | 229 CHECK(!new_handles || new_handles->size() == 0); |
| 243 return; | 230 return; |
| 244 } | 231 } |
| 245 | 232 |
| 246 CHECK(new_handles && new_handles->size() <= max_handles_); | 233 CHECK(new_handles && new_handles->size() <= max_handles_); |
| 247 header_->num_handles = static_cast<uint16_t>(new_handles->size()); | 234 header_->num_handles = static_cast<uint16_t>(new_handles->size()); |
| 235 std::swap(handle_vector_, new_handles); |
| 248 #if defined(OS_WIN) | 236 #if defined(OS_WIN) |
| 249 memcpy(handles(), new_handles->data(), | 237 memset(handles_, 0, extra_header_size()); |
| 250 sizeof(PlatformHandle) * new_handles->size()); | 238 for (size_t i = 0; i < handle_vector_->size(); i++) |
| 251 new_handles->clear(); | 239 handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle); |
| 252 #else | |
| 253 std::swap(handle_vector_, new_handles); | |
| 254 #endif // defined(OS_WIN) | 240 #endif // defined(OS_WIN) |
| 255 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) | 241 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 256 | 242 |
| 257 #if defined(OS_MACOSX) && !defined(OS_IOS) | 243 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 258 size_t mach_port_index = 0; | 244 size_t mach_port_index = 0; |
| 259 if (mach_ports_header_) { | 245 if (mach_ports_header_) { |
| 260 for (size_t i = 0; i < max_handles_; ++i) { | 246 for (size_t i = 0; i < max_handles_; ++i) { |
| 261 mach_ports_header_->entries[i] = | 247 mach_ports_header_->entries[i] = |
| 262 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 248 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 263 } | 249 } |
| 264 for (size_t i = 0; i < handle_vector_->size(); i++) { | 250 for (size_t i = 0; i < handle_vector_->size(); i++) { |
| 265 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || | 251 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || |
| 266 (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { | 252 (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { |
| 267 mach_port_t port = (*handle_vector_)[i].port; | 253 mach_port_t port = (*handle_vector_)[i].port; |
| 268 mach_ports_header_->entries[mach_port_index].index = i; | 254 mach_ports_header_->entries[mach_port_index].index = i; |
| 269 mach_ports_header_->entries[mach_port_index].mach_port = port; | 255 mach_ports_header_->entries[mach_port_index].mach_port = port; |
| 270 mach_port_index++; | 256 mach_port_index++; |
| 271 } | 257 } |
| 272 } | 258 } |
| 273 mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index); | 259 mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index); |
| 274 } | 260 } |
| 275 #endif | 261 #endif |
| 276 } | 262 } |
| 277 | 263 |
| 278 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { | 264 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { |
| 279 #if defined(OS_WIN) | 265 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 280 if (header_->num_handles == 0) | |
| 281 return ScopedPlatformHandleVectorPtr(); | |
| 282 ScopedPlatformHandleVectorPtr moved_handles( | |
| 283 new PlatformHandleVector(header_->num_handles)); | |
| 284 for (size_t i = 0; i < header_->num_handles; ++i) | |
| 285 std::swap(moved_handles->at(i), handles()[i]); | |
| 286 header_->num_handles = 0; | |
| 287 return moved_handles; | |
| 288 #elif defined(OS_MACOSX) && !defined(OS_IOS) | |
| 289 if (mach_ports_header_) { | 266 if (mach_ports_header_) { |
| 290 for (size_t i = 0; i < max_handles_; ++i) { | 267 for (size_t i = 0; i < max_handles_; ++i) { |
| 291 mach_ports_header_->entries[i] = | 268 mach_ports_header_->entries[i] = |
| 292 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 269 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 293 } | 270 } |
| 294 mach_ports_header_->num_ports = 0; | 271 mach_ports_header_->num_ports = 0; |
| 295 } | 272 } |
| 296 header_->num_handles = 0; | 273 header_->num_handles = 0; |
| 297 return std::move(handle_vector_); | 274 return std::move(handle_vector_); |
| 298 #else | 275 #else |
| (...skipping 24 matching lines...) Expand all Loading... |
| 323 return std::move(handle_vector_); | 300 return std::move(handle_vector_); |
| 324 #else | 301 #else |
| 325 return std::move(handle_vector_); | 302 return std::move(handle_vector_); |
| 326 #endif | 303 #endif |
| 327 } | 304 } |
| 328 | 305 |
| 329 #if defined(OS_WIN) | 306 #if defined(OS_WIN) |
| 330 // static | 307 // static |
| 331 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, | 308 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, |
| 332 base::ProcessHandle to_process, | 309 base::ProcessHandle to_process, |
| 333 PlatformHandle* handles, | 310 PlatformHandleVector* handles) { |
| 334 size_t num_handles) { | |
| 335 bool success = true; | 311 bool success = true; |
| 336 for (size_t i = 0; i < num_handles; ++i) { | 312 for (size_t i = 0; i < handles->size(); ++i) { |
| 337 if (!handles[i].is_valid()) { | 313 if (!(*handles)[i].is_valid()) { |
| 338 DLOG(ERROR) << "Refusing to duplicate invalid handle."; | 314 DLOG(ERROR) << "Refusing to duplicate invalid handle."; |
| 339 continue; | 315 continue; |
| 340 } | 316 } |
| 341 DCHECK_EQ(handles[i].owning_process, from_process); | 317 DCHECK_EQ((*handles)[i].owning_process, from_process); |
| 342 BOOL result = DuplicateHandle( | 318 BOOL result = DuplicateHandle( |
| 343 from_process, handles[i].handle, to_process, | 319 from_process, (*handles)[i].handle, to_process, |
| 344 &handles[i].handle, 0, FALSE, | 320 &(*handles)[i].handle, 0, FALSE, |
| 345 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); | 321 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
| 346 if (result) { | 322 if (result) { |
| 347 handles[i].owning_process = to_process; | 323 (*handles)[i].owning_process = to_process; |
| 348 } else { | 324 } else { |
| 349 success = false; | 325 success = false; |
| 350 | 326 |
| 351 // If handle duplication fails, the source handle will already be closed | 327 // If handle duplication fails, the source handle will already be closed |
| 352 // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with | 328 // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with |
| 353 // an invalid handle. | 329 // an invalid handle. |
| 354 handles[i].handle = INVALID_HANDLE_VALUE; | 330 (*handles)[i].handle = INVALID_HANDLE_VALUE; |
| 355 handles[i].owning_process = base::GetCurrentProcessHandle(); | 331 (*handles)[i].owning_process = base::GetCurrentProcessHandle(); |
| 356 } | 332 } |
| 357 } | 333 } |
| 358 return success; | 334 return success; |
| 359 } | 335 } |
| 360 #endif | 336 #endif |
| 361 | 337 |
| 362 // Helper class for managing a Channel's read buffer allocations. This maintains | 338 // Helper class for managing a Channel's read buffer allocations. This maintains |
| 363 // a single contiguous buffer with the layout: | 339 // a single contiguous buffer with the layout: |
| 364 // | 340 // |
| 365 // [discarded bytes][occupied bytes][unoccupied bytes] | 341 // [discarded bytes][occupied bytes][unoccupied bytes] |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 568 |
| 593 bool Channel::OnControlMessage(Message::Header::MessageType message_type, | 569 bool Channel::OnControlMessage(Message::Header::MessageType message_type, |
| 594 const void* payload, | 570 const void* payload, |
| 595 size_t payload_size, | 571 size_t payload_size, |
| 596 ScopedPlatformHandleVectorPtr handles) { | 572 ScopedPlatformHandleVectorPtr handles) { |
| 597 return false; | 573 return false; |
| 598 } | 574 } |
| 599 | 575 |
| 600 } // namespace edk | 576 } // namespace edk |
| 601 } // namespace mojo | 577 } // namespace mojo |
| OLD | NEW |