| 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/node_channel.h" | 5 #include "mojo/edk/system/node_channel.h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 Channel::MessagePtr message( | 120 Channel::MessagePtr message( |
| 121 new Channel::Message(sizeof(Header) + payload_size, num_handles)); | 121 new Channel::Message(sizeof(Header) + payload_size, num_handles)); |
| 122 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); | 122 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); |
| 123 header->type = type; | 123 header->type = type; |
| 124 header->padding = 0; | 124 header->padding = 0; |
| 125 *out_data = reinterpret_cast<DataType*>(&header[1]); | 125 *out_data = reinterpret_cast<DataType*>(&header[1]); |
| 126 return message; | 126 return message; |
| 127 } | 127 } |
| 128 | 128 |
| 129 template <typename DataType> | 129 template <typename DataType> |
| 130 void GetMessagePayload(const void* bytes, DataType** out_data) { | 130 bool GetMessagePayload(const void* bytes, |
| 131 size_t num_bytes, |
| 132 DataType** out_data) { |
| 133 static_assert(sizeof(DataType) > 0, "DataType must have non-zero size."); |
| 134 if (num_bytes < sizeof(Header) + sizeof(DataType)) |
| 135 return false; |
| 131 *out_data = reinterpret_cast<const DataType*>( | 136 *out_data = reinterpret_cast<const DataType*>( |
| 132 static_cast<const char*>(bytes) + sizeof(Header)); | 137 static_cast<const char*>(bytes) + sizeof(Header)); |
| 138 return true; |
| 133 } | 139 } |
| 134 | 140 |
| 135 } // namespace | 141 } // namespace |
| 136 | 142 |
| 137 // static | 143 // static |
| 138 scoped_refptr<NodeChannel> NodeChannel::Create( | 144 scoped_refptr<NodeChannel> NodeChannel::Create( |
| 139 Delegate* delegate, | 145 Delegate* delegate, |
| 140 ScopedPlatformHandle platform_handle, | 146 ScopedPlatformHandle platform_handle, |
| 141 scoped_refptr<base::TaskRunner> io_task_runner) { | 147 scoped_refptr<base::TaskRunner> io_task_runner) { |
| 142 return new NodeChannel(delegate, std::move(platform_handle), io_task_runner); | 148 return new NodeChannel(delegate, std::move(platform_handle), io_task_runner); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 { | 414 { |
| 409 MachPortRelay* relay = delegate_->GetMachPortRelay(); | 415 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 410 if (handles && !relay) { | 416 if (handles && !relay) { |
| 411 if (!MachPortRelay::ReceivePorts(handles.get())) { | 417 if (!MachPortRelay::ReceivePorts(handles.get())) { |
| 412 LOG(ERROR) << "Error receiving mach ports."; | 418 LOG(ERROR) << "Error receiving mach ports."; |
| 413 } | 419 } |
| 414 } | 420 } |
| 415 } | 421 } |
| 416 #endif // defined(OS_WIN) | 422 #endif // defined(OS_WIN) |
| 417 | 423 |
| 424 |
| 425 if (payload_size <= sizeof(Header)) { |
| 426 delegate_->OnChannelError(remote_node_name_); |
| 427 return; |
| 428 } |
| 429 |
| 418 const Header* header = static_cast<const Header*>(payload); | 430 const Header* header = static_cast<const Header*>(payload); |
| 419 switch (header->type) { | 431 switch (header->type) { |
| 420 case MessageType::ACCEPT_CHILD: { | 432 case MessageType::ACCEPT_CHILD: { |
| 421 const AcceptChildData* data; | 433 const AcceptChildData* data; |
| 422 GetMessagePayload(payload, &data); | 434 if (GetMessagePayload(payload, payload_size, &data)) { |
| 423 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, | 435 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, |
| 424 data->token); | 436 data->token); |
| 437 return; |
| 438 } |
| 425 break; | 439 break; |
| 426 } | 440 } |
| 427 | 441 |
| 428 case MessageType::ACCEPT_PARENT: { | 442 case MessageType::ACCEPT_PARENT: { |
| 429 const AcceptParentData* data; | 443 const AcceptParentData* data; |
| 430 GetMessagePayload(payload, &data); | 444 if (GetMessagePayload(payload, payload_size, &data)) { |
| 431 delegate_->OnAcceptParent(remote_node_name_, data->token, | 445 delegate_->OnAcceptParent(remote_node_name_, data->token, |
| 432 data->child_name); | 446 data->child_name); |
| 447 return; |
| 448 } |
| 433 break; | 449 break; |
| 434 } | 450 } |
| 435 | 451 |
| 436 case MessageType::ADD_BROKER_CLIENT: { | 452 case MessageType::ADD_BROKER_CLIENT: { |
| 437 const AddBrokerClientData* data; | 453 const AddBrokerClientData* data; |
| 438 GetMessagePayload(payload, &data); | 454 if (GetMessagePayload(payload, payload_size, &data)) { |
| 439 ScopedPlatformHandle process_handle; | 455 ScopedPlatformHandle process_handle; |
| 440 #if defined(OS_WIN) | 456 #if defined(OS_WIN) |
| 441 if (!handles || handles->size() != 1) { | 457 if (!handles || handles->size() != 1) { |
| 442 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; | 458 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; |
| 443 break; | 459 break; |
| 460 } |
| 461 process_handle = ScopedPlatformHandle(handles->at(0)); |
| 462 handles->clear(); |
| 463 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, |
| 464 process_handle.release().handle); |
| 465 #else |
| 466 if (handles && handles->size() != 0) { |
| 467 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; |
| 468 break; |
| 469 } |
| 470 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, |
| 471 data->process_handle); |
| 472 #endif |
| 473 return; |
| 444 } | 474 } |
| 445 process_handle = ScopedPlatformHandle(handles->at(0)); | |
| 446 handles->clear(); | |
| 447 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 448 process_handle.release().handle); | |
| 449 #else | |
| 450 if (handles && handles->size() != 0) { | |
| 451 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; | |
| 452 break; | |
| 453 } | |
| 454 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 455 data->process_handle); | |
| 456 #endif | |
| 457 break; | 475 break; |
| 458 } | 476 } |
| 459 | 477 |
| 460 case MessageType::BROKER_CLIENT_ADDED: { | 478 case MessageType::BROKER_CLIENT_ADDED: { |
| 461 const BrokerClientAddedData* data; | 479 const BrokerClientAddedData* data; |
| 462 GetMessagePayload(payload, &data); | 480 if (GetMessagePayload(payload, payload_size, &data)) { |
| 463 ScopedPlatformHandle broker_channel; | 481 ScopedPlatformHandle broker_channel; |
| 464 if (!handles || handles->size() != 1) { | 482 if (!handles || handles->size() != 1) { |
| 465 DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; | 483 DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; |
| 466 break; | 484 break; |
| 485 } |
| 486 broker_channel = ScopedPlatformHandle(handles->at(0)); |
| 487 handles->clear(); |
| 488 delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, |
| 489 std::move(broker_channel)); |
| 490 return; |
| 467 } | 491 } |
| 468 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 469 handles->clear(); | |
| 470 delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, | |
| 471 std::move(broker_channel)); | |
| 472 break; | 492 break; |
| 473 } | 493 } |
| 474 | 494 |
| 475 case MessageType::ACCEPT_BROKER_CLIENT: { | 495 case MessageType::ACCEPT_BROKER_CLIENT: { |
| 476 const AcceptBrokerClientData* data; | 496 const AcceptBrokerClientData* data; |
| 477 GetMessagePayload(payload, &data); | 497 if (GetMessagePayload(payload, payload_size, &data)) { |
| 478 ScopedPlatformHandle broker_channel; | 498 ScopedPlatformHandle broker_channel; |
| 479 if (handles && handles->size() > 1) { | 499 if (handles && handles->size() > 1) { |
| 480 DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; | 500 DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; |
| 481 break; | 501 break; |
| 502 } |
| 503 if (handles && handles->size() == 1) { |
| 504 broker_channel = ScopedPlatformHandle(handles->at(0)); |
| 505 handles->clear(); |
| 506 } |
| 507 delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, |
| 508 std::move(broker_channel)); |
| 509 return; |
| 482 } | 510 } |
| 483 if (handles && handles->size() == 1) { | |
| 484 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 485 handles->clear(); | |
| 486 } | |
| 487 delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, | |
| 488 std::move(broker_channel)); | |
| 489 break; | 511 break; |
| 490 } | 512 } |
| 491 | 513 |
| 492 case MessageType::PORTS_MESSAGE: { | 514 case MessageType::PORTS_MESSAGE: { |
| 493 size_t num_handles = handles ? handles->size() : 0; | 515 size_t num_handles = handles ? handles->size() : 0; |
| 494 Channel::MessagePtr message( | 516 Channel::MessagePtr message( |
| 495 new Channel::Message(payload_size, num_handles)); | 517 new Channel::Message(payload_size, num_handles)); |
| 496 message->SetHandles(std::move(handles)); | 518 message->SetHandles(std::move(handles)); |
| 497 memcpy(message->mutable_payload(), payload, payload_size); | 519 memcpy(message->mutable_payload(), payload, payload_size); |
| 498 delegate_->OnPortsMessage(std::move(message)); | 520 delegate_->OnPortsMessage(std::move(message)); |
| 499 break; | 521 return; |
| 500 } | 522 } |
| 501 | 523 |
| 502 case MessageType::REQUEST_PORT_MERGE: { | 524 case MessageType::REQUEST_PORT_MERGE: { |
| 503 const RequestPortMergeData* data; | 525 const RequestPortMergeData* data; |
| 504 GetMessagePayload(payload, &data); | 526 if (GetMessagePayload(payload, payload_size, &data)) { |
| 505 | 527 // Don't accept an empty token. |
| 506 const char* token_data = reinterpret_cast<const char*>(data + 1); | 528 size_t token_size = payload_size - sizeof(*data) - sizeof(Header); |
| 507 const size_t token_size = payload_size - sizeof(*data) - sizeof(Header); | 529 if (token_size == 0) |
| 508 std::string token(token_data, token_size); | 530 break; |
| 509 | 531 std::string token(reinterpret_cast<const char*>(data + 1), token_size); |
| 510 delegate_->OnRequestPortMerge(remote_node_name_, | 532 delegate_->OnRequestPortMerge(remote_node_name_, |
| 511 data->connector_port_name, token); | 533 data->connector_port_name, token); |
| 534 return; |
| 535 } |
| 512 break; | 536 break; |
| 513 } | 537 } |
| 514 | 538 |
| 515 case MessageType::REQUEST_INTRODUCTION: { | 539 case MessageType::REQUEST_INTRODUCTION: { |
| 516 const IntroductionData* data; | 540 const IntroductionData* data; |
| 517 GetMessagePayload(payload, &data); | 541 if (GetMessagePayload(payload, payload_size, &data)) { |
| 518 delegate_->OnRequestIntroduction(remote_node_name_, data->name); | 542 delegate_->OnRequestIntroduction(remote_node_name_, data->name); |
| 543 return; |
| 544 } |
| 519 break; | 545 break; |
| 520 } | 546 } |
| 521 | 547 |
| 522 case MessageType::INTRODUCE: { | 548 case MessageType::INTRODUCE: { |
| 523 const IntroductionData* data; | 549 const IntroductionData* data; |
| 524 GetMessagePayload(payload, &data); | 550 if (GetMessagePayload(payload, payload_size, &data)) { |
| 525 if (handles && handles->size() > 1) { | 551 if (handles && handles->size() > 1) { |
| 526 DLOG(ERROR) << "Dropping invalid introduction message."; | 552 DLOG(ERROR) << "Dropping invalid introduction message."; |
| 527 break; | 553 break; |
| 554 } |
| 555 ScopedPlatformHandle channel_handle; |
| 556 if (handles && handles->size() == 1) { |
| 557 channel_handle = ScopedPlatformHandle(handles->at(0)); |
| 558 handles->clear(); |
| 559 } |
| 560 delegate_->OnIntroduce(remote_node_name_, data->name, |
| 561 std::move(channel_handle)); |
| 562 return; |
| 528 } | 563 } |
| 529 ScopedPlatformHandle channel_handle; | |
| 530 if (handles && handles->size() == 1) { | |
| 531 channel_handle = ScopedPlatformHandle(handles->at(0)); | |
| 532 handles->clear(); | |
| 533 } | |
| 534 delegate_->OnIntroduce(remote_node_name_, data->name, | |
| 535 std::move(channel_handle)); | |
| 536 break; | 564 break; |
| 537 } | 565 } |
| 538 | 566 |
| 539 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) | 567 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
| 540 case MessageType::RELAY_PORTS_MESSAGE: { | 568 case MessageType::RELAY_PORTS_MESSAGE: { |
| 541 base::ProcessHandle from_process; | 569 base::ProcessHandle from_process; |
| 542 { | 570 { |
| 543 base::AutoLock lock(remote_process_handle_lock_); | 571 base::AutoLock lock(remote_process_handle_lock_); |
| 544 from_process = remote_process_handle_; | 572 from_process = remote_process_handle_; |
| 545 } | 573 } |
| 546 const RelayPortsMessageData* data; | 574 const RelayPortsMessageData* data; |
| 547 GetMessagePayload(payload, &data); | 575 if (GetMessagePayload(payload, payload_size, &data)) { |
| 548 const void* message_start = data + 1; | 576 // Don't try to relay an empty message. |
| 549 Channel::MessagePtr message = Channel::Message::Deserialize( | 577 if (payload_size <= sizeof(Header) + sizeof(RelayPortsMessageData)) |
| 550 message_start, payload_size - sizeof(Header) - sizeof(*data)); | 578 break; |
| 551 if (!message) { | 579 |
| 552 DLOG(ERROR) << "Dropping invalid relay message."; | 580 const void* message_start = data + 1; |
| 553 break; | 581 Channel::MessagePtr message = Channel::Message::Deserialize( |
| 554 } | 582 message_start, payload_size - sizeof(Header) - sizeof(*data)); |
| 555 #if defined(OS_MACOSX) && !defined(OS_IOS) | 583 if (!message) { |
| 556 message->SetHandles(std::move(handles)); | 584 DLOG(ERROR) << "Dropping invalid relay message."; |
| 557 MachPortRelay* relay = delegate_->GetMachPortRelay(); | |
| 558 if (!relay) { | |
| 559 LOG(ERROR) << "Receiving mach ports without a port relay from " | |
| 560 << remote_node_name_ << ". Dropping message."; | |
| 561 break; | |
| 562 } | |
| 563 { | |
| 564 base::AutoLock lock(pending_mach_messages_lock_); | |
| 565 if (relay->port_provider()->TaskForPid(from_process) == | |
| 566 MACH_PORT_NULL) { | |
| 567 pending_relay_messages_.push( | |
| 568 std::make_pair(data->destination, std::move(message))); | |
| 569 break; | 585 break; |
| 570 } | 586 } |
| 587 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 588 message->SetHandles(std::move(handles)); |
| 589 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 590 if (!relay) { |
| 591 LOG(ERROR) << "Receiving mach ports without a port relay from " |
| 592 << remote_node_name_ << ". Dropping message."; |
| 593 break; |
| 594 } |
| 595 { |
| 596 base::AutoLock lock(pending_mach_messages_lock_); |
| 597 if (relay->port_provider()->TaskForPid(from_process) == |
| 598 MACH_PORT_NULL) { |
| 599 pending_relay_messages_.push( |
| 600 std::make_pair(data->destination, std::move(message))); |
| 601 break; |
| 602 } |
| 603 } |
| 604 #endif |
| 605 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, |
| 606 data->destination, std::move(message)); |
| 607 return; |
| 571 } | 608 } |
| 572 #endif | |
| 573 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, | |
| 574 data->destination, std::move(message)); | |
| 575 break; | 609 break; |
| 576 } | 610 } |
| 577 #endif | 611 #endif |
| 578 | 612 |
| 579 default: | 613 default: |
| 580 DLOG(ERROR) << "Received unknown message type " | |
| 581 << static_cast<uint32_t>(header->type) << " from node " | |
| 582 << remote_node_name_; | |
| 583 delegate_->OnChannelError(remote_node_name_); | |
| 584 break; | 614 break; |
| 585 } | 615 } |
| 616 |
| 617 DLOG(ERROR) << "Received invalid message. Closing channel."; |
| 618 delegate_->OnChannelError(remote_node_name_); |
| 586 } | 619 } |
| 587 | 620 |
| 588 void NodeChannel::OnChannelError() { | 621 void NodeChannel::OnChannelError() { |
| 589 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 622 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
| 590 | 623 |
| 591 RequestContext request_context(RequestContext::Source::SYSTEM); | 624 RequestContext request_context(RequestContext::Source::SYSTEM); |
| 592 | 625 |
| 593 ShutDown(); | 626 ShutDown(); |
| 594 // |OnChannelError()| may cause |this| to be destroyed, but still need access | 627 // |OnChannelError()| may cause |this| to be destroyed, but still need access |
| 595 // to the name name after that destruction. So may a copy of | 628 // to the name name after that destruction. So may a copy of |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 | 744 |
| 712 base::AutoLock lock(channel_lock_); | 745 base::AutoLock lock(channel_lock_); |
| 713 if (!channel_) | 746 if (!channel_) |
| 714 DLOG(ERROR) << "Dropping message on closed channel."; | 747 DLOG(ERROR) << "Dropping message on closed channel."; |
| 715 else | 748 else |
| 716 channel_->Write(std::move(message)); | 749 channel_->Write(std::move(message)); |
| 717 } | 750 } |
| 718 | 751 |
| 719 } // namespace edk | 752 } // namespace edk |
| 720 } // namespace mojo | 753 } // namespace mojo |
| OLD | NEW |