| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/message_pipe_dispatcher.h" | 5 #include "mojo/edk/system/message_pipe_dispatcher.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 MojoReadMessageFlags flags) { | 318 MojoReadMessageFlags flags) { |
| 319 { | 319 { |
| 320 base::AutoLock lock(signal_lock_); | 320 base::AutoLock lock(signal_lock_); |
| 321 // We can't read from a port that's closed or in transit! | 321 // We can't read from a port that's closed or in transit! |
| 322 if (port_closed_ || in_transit_) | 322 if (port_closed_ || in_transit_) |
| 323 return MOJO_RESULT_INVALID_ARGUMENT; | 323 return MOJO_RESULT_INVALID_ARGUMENT; |
| 324 } | 324 } |
| 325 | 325 |
| 326 bool no_space = false; | 326 bool no_space = false; |
| 327 bool may_discard = flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD; | 327 bool may_discard = flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD; |
| 328 bool invalid_message = false; |
| 328 | 329 |
| 329 // Ensure the provided buffers are large enough to hold the next message. | 330 // Ensure the provided buffers are large enough to hold the next message. |
| 330 // GetMessageIf provides an atomic way to test the next message without | 331 // GetMessageIf provides an atomic way to test the next message without |
| 331 // committing to removing it from the port's underlying message queue until | 332 // committing to removing it from the port's underlying message queue until |
| 332 // we are sure we can consume it. | 333 // we are sure we can consume it. |
| 333 | 334 |
| 334 ports::ScopedMessage ports_message; | 335 ports::ScopedMessage ports_message; |
| 335 int rv = node_controller_->node()->GetMessageIf( | 336 int rv = node_controller_->node()->GetMessageIf( |
| 336 port_, | 337 port_, |
| 337 [num_bytes, num_handles, &no_space, &may_discard]( | 338 [num_bytes, num_handles, &no_space, &may_discard, &invalid_message]( |
| 338 const ports::Message& next_message) { | 339 const ports::Message& next_message) { |
| 339 const PortsMessage& message = | 340 const PortsMessage& message = |
| 340 static_cast<const PortsMessage&>(next_message); | 341 static_cast<const PortsMessage&>(next_message); |
| 341 DCHECK_GE(message.num_payload_bytes(), sizeof(MessageHeader)); | 342 if (message.num_payload_bytes() < sizeof(MessageHeader)) { |
| 343 invalid_message = true; |
| 344 return true; |
| 345 } |
| 342 | 346 |
| 343 const MessageHeader* header = | 347 const MessageHeader* header = |
| 344 static_cast<const MessageHeader*>(message.payload_bytes()); | 348 static_cast<const MessageHeader*>(message.payload_bytes()); |
| 345 DCHECK_LE(header->header_size, message.num_payload_bytes()); | 349 if (header->header_size > message.num_payload_bytes()) { |
| 350 invalid_message = true; |
| 351 return true; |
| 352 } |
| 346 | 353 |
| 347 uint32_t bytes_to_read = 0; | 354 uint32_t bytes_to_read = 0; |
| 348 uint32_t bytes_available = | 355 uint32_t bytes_available = |
| 349 static_cast<uint32_t>(message.num_payload_bytes()) - | 356 static_cast<uint32_t>(message.num_payload_bytes()) - |
| 350 header->header_size; | 357 header->header_size; |
| 351 if (num_bytes) { | 358 if (num_bytes) { |
| 352 bytes_to_read = std::min(*num_bytes, bytes_available); | 359 bytes_to_read = std::min(*num_bytes, bytes_available); |
| 353 *num_bytes = bytes_available; | 360 *num_bytes = bytes_available; |
| 354 } | 361 } |
| 355 | 362 |
| 356 uint32_t handles_to_read = 0; | 363 uint32_t handles_to_read = 0; |
| 357 uint32_t handles_available = header->num_dispatchers; | 364 uint32_t handles_available = header->num_dispatchers; |
| 358 if (num_handles) { | 365 if (num_handles) { |
| 359 handles_to_read = std::min(*num_handles, handles_available); | 366 handles_to_read = std::min(*num_handles, handles_available); |
| 360 *num_handles = handles_available; | 367 *num_handles = handles_available; |
| 361 } | 368 } |
| 362 | 369 |
| 363 if (bytes_to_read < bytes_available || | 370 if (bytes_to_read < bytes_available || |
| 364 handles_to_read < handles_available) { | 371 handles_to_read < handles_available) { |
| 365 no_space = true; | 372 no_space = true; |
| 366 return may_discard; | 373 return may_discard; |
| 367 } | 374 } |
| 368 | 375 |
| 369 return true; | 376 return true; |
| 370 }, | 377 }, |
| 371 &ports_message); | 378 &ports_message); |
| 372 | 379 |
| 380 if (invalid_message) |
| 381 return MOJO_RESULT_UNKNOWN; |
| 382 |
| 373 if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { | 383 if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { |
| 374 if (rv == ports::ERROR_PORT_UNKNOWN || | 384 if (rv == ports::ERROR_PORT_UNKNOWN || |
| 375 rv == ports::ERROR_PORT_STATE_UNEXPECTED) | 385 rv == ports::ERROR_PORT_STATE_UNEXPECTED) |
| 376 return MOJO_RESULT_INVALID_ARGUMENT; | 386 return MOJO_RESULT_INVALID_ARGUMENT; |
| 377 | 387 |
| 378 NOTREACHED(); | 388 NOTREACHED(); |
| 379 return MOJO_RESULT_UNKNOWN; // TODO: Add a better error code here? | 389 return MOJO_RESULT_UNKNOWN; // TODO: Add a better error code here? |
| 380 } | 390 } |
| 381 | 391 |
| 382 if (no_space) { | 392 if (no_space) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 403 // in which to receive it. | 413 // in which to receive it. |
| 404 | 414 |
| 405 scoped_ptr<PortsMessage> message( | 415 scoped_ptr<PortsMessage> message( |
| 406 static_cast<PortsMessage*>(ports_message.release())); | 416 static_cast<PortsMessage*>(ports_message.release())); |
| 407 | 417 |
| 408 const MessageHeader* header = | 418 const MessageHeader* header = |
| 409 static_cast<const MessageHeader*>(message->payload_bytes()); | 419 static_cast<const MessageHeader*>(message->payload_bytes()); |
| 410 const DispatcherHeader* dispatcher_headers = | 420 const DispatcherHeader* dispatcher_headers = |
| 411 reinterpret_cast<const DispatcherHeader*>(header + 1); | 421 reinterpret_cast<const DispatcherHeader*>(header + 1); |
| 412 | 422 |
| 413 const char* dispatcher_data = reinterpret_cast<const char*>( | 423 if (header->num_dispatchers > std::numeric_limits<uint16_t>::max()) |
| 414 dispatcher_headers + header->num_dispatchers); | 424 return MOJO_RESULT_UNKNOWN; |
| 415 | 425 |
| 416 // Deserialize dispatchers. | 426 // Deserialize dispatchers. |
| 417 if (header->num_dispatchers > 0) { | 427 if (header->num_dispatchers > 0) { |
| 418 CHECK(handles); | 428 CHECK(handles); |
| 419 std::vector<DispatcherInTransit> dispatchers(header->num_dispatchers); | 429 std::vector<DispatcherInTransit> dispatchers(header->num_dispatchers); |
| 420 size_t data_payload_index = sizeof(MessageHeader) + | 430 size_t data_payload_index = sizeof(MessageHeader) + |
| 421 header->num_dispatchers * sizeof(DispatcherHeader); | 431 header->num_dispatchers * sizeof(DispatcherHeader); |
| 432 if (data_payload_index > header->header_size) |
| 433 return MOJO_RESULT_UNKNOWN; |
| 434 const char* dispatcher_data = reinterpret_cast<const char*>( |
| 435 dispatcher_headers + header->num_dispatchers); |
| 422 size_t port_index = 0; | 436 size_t port_index = 0; |
| 423 size_t platform_handle_index = 0; | 437 size_t platform_handle_index = 0; |
| 424 for (size_t i = 0; i < header->num_dispatchers; ++i) { | 438 for (size_t i = 0; i < header->num_dispatchers; ++i) { |
| 425 const DispatcherHeader& dh = dispatcher_headers[i]; | 439 const DispatcherHeader& dh = dispatcher_headers[i]; |
| 426 Type type = static_cast<Type>(dh.type); | 440 Type type = static_cast<Type>(dh.type); |
| 427 | 441 |
| 428 DCHECK_GE(message->num_payload_bytes(), | 442 size_t next_payload_index = data_payload_index + dh.num_bytes; |
| 429 data_payload_index + dh.num_bytes); | 443 if (message->num_payload_bytes() < next_payload_index || |
| 430 DCHECK_GE(message->num_ports(), | 444 next_payload_index < data_payload_index) { |
| 431 port_index + dh.num_ports); | 445 return MOJO_RESULT_UNKNOWN; |
| 432 DCHECK_GE(message->num_handles(), | 446 } |
| 433 platform_handle_index + dh.num_platform_handles); | 447 |
| 448 size_t next_port_index = port_index + dh.num_ports; |
| 449 if (message->num_ports() < next_port_index || |
| 450 next_port_index < port_index) |
| 451 return MOJO_RESULT_UNKNOWN; |
| 452 |
| 453 size_t next_platform_handle_index = |
| 454 platform_handle_index + dh.num_platform_handles; |
| 455 if (message->num_handles() < next_platform_handle_index || |
| 456 next_platform_handle_index < platform_handle_index) { |
| 457 return MOJO_RESULT_UNKNOWN; |
| 458 } |
| 434 | 459 |
| 435 PlatformHandle* out_handles = | 460 PlatformHandle* out_handles = |
| 436 message->num_handles() ? message->handles() + platform_handle_index | 461 message->num_handles() ? message->handles() + platform_handle_index |
| 437 : nullptr; | 462 : nullptr; |
| 438 dispatchers[i].dispatcher = Dispatcher::Deserialize( | 463 dispatchers[i].dispatcher = Dispatcher::Deserialize( |
| 439 type, dispatcher_data, dh.num_bytes, message->ports() + port_index, | 464 type, dispatcher_data, dh.num_bytes, message->ports() + port_index, |
| 440 dh.num_ports, out_handles, dh.num_platform_handles); | 465 dh.num_ports, out_handles, dh.num_platform_handles); |
| 441 if (!dispatchers[i].dispatcher) | 466 if (!dispatchers[i].dispatcher) |
| 442 return MOJO_RESULT_UNKNOWN; | 467 return MOJO_RESULT_UNKNOWN; |
| 443 | 468 |
| 444 dispatcher_data += dh.num_bytes; | 469 dispatcher_data += dh.num_bytes; |
| 445 data_payload_index += dh.num_bytes; | 470 data_payload_index = next_payload_index; |
| 446 port_index += dh.num_ports; | 471 port_index = next_port_index; |
| 447 platform_handle_index += dh.num_platform_handles; | 472 platform_handle_index = next_platform_handle_index; |
| 448 } | 473 } |
| 449 | 474 |
| 450 if (!node_controller_->core()->AddDispatchersFromTransit(dispatchers, | 475 if (!node_controller_->core()->AddDispatchersFromTransit(dispatchers, |
| 451 handles)) | 476 handles)) |
| 452 return MOJO_RESULT_UNKNOWN; | 477 return MOJO_RESULT_UNKNOWN; |
| 453 } | 478 } |
| 454 | 479 |
| 455 // Copy message bytes. | 480 // Copy message bytes. |
| 456 DCHECK_GE(message->num_payload_bytes(), header->header_size); | 481 DCHECK_GE(message->num_payload_bytes(), header->header_size); |
| 457 const char* payload = reinterpret_cast<const char*>(message->payload_bytes()); | 482 const char* payload = reinterpret_cast<const char*>(message->payload_bytes()); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 DVLOG(1) << "Peer closure detected on message pipe " << pipe_id_ | 693 DVLOG(1) << "Peer closure detected on message pipe " << pipe_id_ |
| 669 << " endpoint " << endpoint_ << " [port=" << port_.name() << "]"; | 694 << " endpoint " << endpoint_ << " [port=" << port_.name() << "]"; |
| 670 } | 695 } |
| 671 #endif | 696 #endif |
| 672 | 697 |
| 673 awakables_.AwakeForStateChange(GetHandleSignalsStateNoLock()); | 698 awakables_.AwakeForStateChange(GetHandleSignalsStateNoLock()); |
| 674 } | 699 } |
| 675 | 700 |
| 676 } // namespace edk | 701 } // namespace edk |
| 677 } // namespace mojo | 702 } // namespace mojo |
| OLD | NEW |