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