diff options
Diffstat (limited to 'chromium/mojo')
| -rw-r--r-- | chromium/mojo/edk/system/broker_host_posix.cc | 20 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/channel.cc | 49 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/channel.h | 20 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/channel_posix.cc | 64 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/channel_win.cc | 20 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/node_channel.cc | 228 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/node_channel.h | 3 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/node_controller.cc | 22 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/node_controller.h | 3 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/ports/message.cc | 18 | ||||
| -rw-r--r-- | chromium/mojo/edk/system/ports/message.h | 5 |
11 files changed, 282 insertions, 170 deletions
diff --git a/chromium/mojo/edk/system/broker_host_posix.cc b/chromium/mojo/edk/system/broker_host_posix.cc index 8734874a8ec..7a5c54e551e 100644 --- a/chromium/mojo/edk/system/broker_host_posix.cc +++ b/chromium/mojo/edk/system/broker_host_posix.cc @@ -82,19 +82,27 @@ void BrokerHost::OnBufferRequest(size_t num_bytes) { void BrokerHost::OnChannelMessage(const void* payload, size_t payload_size, ScopedPlatformHandleVectorPtr handles) { + if (payload_size < sizeof(BrokerMessageHeader)) + return; + const BrokerMessageHeader* header = static_cast<const BrokerMessageHeader*>(payload); switch (header->type) { - case BrokerMessageType::BUFFER_REQUEST: { - const BufferRequestData* request = - reinterpret_cast<const BufferRequestData*>(header + 1); - OnBufferRequest(request->size); + case BrokerMessageType::BUFFER_REQUEST: + if (payload_size == + sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) { + const BufferRequestData* request = + reinterpret_cast<const BufferRequestData*>(header + 1); + OnBufferRequest(request->size); + return; + } break; - } + default: - LOG(ERROR) << "Unexpected broker message type: " << header->type; break; } + + LOG(ERROR) << "Unexpected broker message type: " << header->type; } void BrokerHost::OnChannelError() { diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/edk/system/channel.cc index ac666cf3790..107a446133e 100644 --- a/chromium/mojo/edk/system/channel.cc +++ b/chromium/mojo/edk/system/channel.cc @@ -156,14 +156,20 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data, DCHECK_EQ(message->extra_header_size(), extra_header_size); DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); - // Copy all payload bytes. - memcpy(message->mutable_payload(), - static_cast<const char*>(data) + header->num_header_bytes, - data_num_bytes - header->num_header_bytes); - // Copy extra header bytes. - memcpy(message->mutable_extra_header(), - static_cast<const char*>(data) + sizeof(Header), - message->extra_header_size()); + if (data_num_bytes > header->num_header_bytes) { + // Copy all payload bytes. + memcpy(message->mutable_payload(), + static_cast<const char*>(data) + header->num_header_bytes, + data_num_bytes - header->num_header_bytes); + } + + if (message->extra_header_size()) { + // Copy extra header bytes. + memcpy(message->mutable_extra_header(), + static_cast<const char*>(data) + sizeof(Header), + message->extra_header_size()); + } + message->header_->num_handles = header->num_handles; return message; @@ -485,9 +491,14 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) : nullptr; #else + if (header->num_header_bytes < sizeof(Message::Header) || + header->num_header_bytes > header->num_bytes) { + LOG(ERROR) << "Invalid message header size: " << header->num_header_bytes; + return false; + } size_t extra_header_size = header->num_header_bytes - sizeof(Message::Header); - const void* extra_header = header + 1; + const void* extra_header = extra_header_size ? header + 1 : nullptr; size_t payload_size = header->num_bytes - header->num_header_bytes; void* payload = payload_size ? reinterpret_cast<Message::Header*>( @@ -498,8 +509,11 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { ScopedPlatformHandleVectorPtr handles; if (header->num_handles > 0) { - handles = GetReadPlatformHandles(header->num_handles, extra_header, - extra_header_size); + if (!GetReadPlatformHandles(header->num_handles, extra_header, + extra_header_size, &handles)) { + return false; + } + if (!handles) { // Not enough handles available for this message. break; @@ -508,8 +522,10 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { // We've got a complete message! Dispatch it and try another. if (header->message_type != Message::Header::MessageType::NORMAL) { - OnControlMessage(header->message_type, payload, payload_size, - std::move(handles)); + if (!OnControlMessage(header->message_type, payload, payload_size, + std::move(handles))) { + return false; + } did_dispatch_message = true; } else if (delegate_) { delegate_->OnChannelMessage(payload, payload_size, std::move(handles)); @@ -528,5 +544,12 @@ void Channel::OnError() { delegate_->OnChannelError(); } +bool Channel::OnControlMessage(Message::Header::MessageType message_type, + const void* payload, + size_t payload_size, + ScopedPlatformHandleVectorPtr handles) { + return false; +} + } // namespace edk } // namespace mojo diff --git a/chromium/mojo/edk/system/channel.h b/chromium/mojo/edk/system/channel.h index 9932c9c71fc..74b62da8664 100644 --- a/chromium/mojo/edk/system/channel.h +++ b/chromium/mojo/edk/system/channel.h @@ -232,17 +232,25 @@ class Channel : public base::RefCountedThreadSafe<Channel> { // |extra_header| and |extra_header_size| correspond to the extra header data. // Depending on the Channel implementation, this body may encode platform // handles, or handles may be stored and managed elsewhere by the - // implementation. If |num_handles| handles cannot be returned, this must - // return null. - virtual ScopedPlatformHandleVectorPtr GetReadPlatformHandles( + // implementation. + // + // Returns |false| on unrecoverable error (i.e. the Channel should be closed). + // Returns |true| otherwise. Note that it is possible on some platforms for an + // insufficient number of handles to be available when this call is made, but + // this is not necessarily an error condition. In such cases this returns + // |true| but |*handles| will also be reset to null. + virtual bool GetReadPlatformHandles( size_t num_handles, const void* extra_header, - size_t extra_header_size) = 0; + size_t extra_header_size, + ScopedPlatformHandleVectorPtr* handles) = 0; - virtual void OnControlMessage(Message::Header::MessageType message_type, + // Handles a received control message. Returns |true| if the message is + // accepted, or |false| otherwise. + virtual bool OnControlMessage(Message::Header::MessageType message_type, const void* payload, size_t payload_size, - ScopedPlatformHandleVectorPtr handles) {} + ScopedPlatformHandleVectorPtr handles); private: friend class base::RefCountedThreadSafe<Channel>; diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/edk/system/channel_posix.cc index bc759e0c159..772a608698b 100644 --- a/chromium/mojo/edk/system/channel_posix.cc +++ b/chromium/mojo/edk/system/channel_posix.cc @@ -9,6 +9,8 @@ #include <algorithm> #include <deque> +#include <limits> +#include <memory> #include "base/bind.h" #include "base/location.h" @@ -132,10 +134,13 @@ class ChannelPosix : public Channel, } } - ScopedPlatformHandleVectorPtr GetReadPlatformHandles( + bool GetReadPlatformHandles( size_t num_handles, const void* extra_header, - size_t extra_header_size) override { + size_t extra_header_size, + ScopedPlatformHandleVectorPtr* handles) override { + if (num_handles > std::numeric_limits<uint16_t>::max()) + return false; #if defined(OS_MACOSX) && !defined(OS_IOS) // On OSX, we can have mach ports which are located in the extra header // section. @@ -149,40 +154,42 @@ class ChannelPosix : public Channel, num_mach_ports++; } CHECK(num_mach_ports <= num_handles); - if (incoming_platform_handles_.size() + num_mach_ports < num_handles) - return nullptr; + if (incoming_platform_handles_.size() + num_mach_ports < num_handles) { + handles->reset(); + return true; + } - ScopedPlatformHandleVectorPtr handles( - new PlatformHandleVector(num_handles)); + handles->reset(new PlatformHandleVector(num_handles)); for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) { if (mach_port_index < num_mach_ports && mach_ports[mach_port_index].index == i) { - (*handles)[i] = PlatformHandle( + (*handles)->at(i) = PlatformHandle( static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port)); - CHECK((*handles)[i].type == PlatformHandle::Type::MACH); + CHECK((*handles)->at(i).type == PlatformHandle::Type::MACH); // These are actually just Mach port names until they're resolved from // the remote process. - (*handles)[i].type = PlatformHandle::Type::MACH_NAME; + (*handles)->at(i).type = PlatformHandle::Type::MACH_NAME; mach_port_index++; } else { CHECK(!incoming_platform_handles_.empty()); - (*handles)[i] = incoming_platform_handles_.front(); + (*handles)->at(i) = incoming_platform_handles_.front(); incoming_platform_handles_.pop_front(); } } #else - if (incoming_platform_handles_.size() < num_handles) - return nullptr; + if (incoming_platform_handles_.size() < num_handles) { + handles->reset(); + return true; + } - ScopedPlatformHandleVectorPtr handles( - new PlatformHandleVector(num_handles)); + handles->reset(new PlatformHandleVector(num_handles)); for (size_t i = 0; i < num_handles; ++i) { - (*handles)[i] = incoming_platform_handles_.front(); + (*handles)->at(i) = incoming_platform_handles_.front(); incoming_platform_handles_.pop_front(); } #endif - return handles; + return true; } private: @@ -396,30 +403,37 @@ class ChannelPosix : public Channel, } #if defined(OS_MACOSX) - void OnControlMessage(Message::Header::MessageType message_type, + bool OnControlMessage(Message::Header::MessageType message_type, const void* payload, size_t payload_size, ScopedPlatformHandleVectorPtr handles) override { switch (message_type) { case Message::Header::MessageType::HANDLES_SENT: { + if (payload_size == 0) + break; MessagePtr message(new Channel::Message( payload_size, 0, Message::Header::MessageType::HANDLES_SENT_ACK)); memcpy(message->mutable_payload(), payload, payload_size); Write(std::move(message)); - break; + return true; } + case Message::Header::MessageType::HANDLES_SENT_ACK: { + size_t num_fds = payload_size / sizeof(int); + if (num_fds == 0 || payload_size % sizeof(int) != 0) + break; + const int* fds = reinterpret_cast<const int*>(payload); - size_t num_fds = payload_size / sizeof(*fds); - if (payload_size % sizeof(*fds) != 0 || !CloseHandles(fds, num_fds)) { - io_task_runner_->PostTask(FROM_HERE, - base::Bind(&ChannelPosix::OnError, this)); - } - break; + if (!CloseHandles(fds, num_fds)) + break; + return true; } + default: - NOTREACHED(); + break; } + + return false; } // Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/edk/system/channel_win.cc index 1eeb2f644fe..465ba62dbba 100644 --- a/chromium/mojo/edk/system/channel_win.cc +++ b/chromium/mojo/edk/system/channel_win.cc @@ -9,6 +9,8 @@ #include <algorithm> #include <deque> +#include <limits> +#include <memory> #include "base/bind.h" #include "base/location.h" @@ -119,18 +121,20 @@ class ChannelWin : public Channel, } } - ScopedPlatformHandleVectorPtr GetReadPlatformHandles( + bool GetReadPlatformHandles( size_t num_handles, const void* extra_header, - size_t extra_header_size) override { + size_t extra_header_size, + ScopedPlatformHandleVectorPtr* handles) override { + if (num_handles > std::numeric_limits<uint16_t>::max()) + return false; size_t handles_size = sizeof(PlatformHandle) * num_handles; if (handles_size > extra_header_size) - return nullptr; - - ScopedPlatformHandleVectorPtr handles( - new PlatformHandleVector(num_handles)); - memcpy(handles->data(), extra_header, handles_size); - return handles; + return false; + DCHECK(extra_header); + handles->reset(new PlatformHandleVector(num_handles)); + memcpy((*handles)->data(), extra_header, handles_size); + return true; } private: diff --git a/chromium/mojo/edk/system/node_channel.cc b/chromium/mojo/edk/system/node_channel.cc index 1be5e47cec7..dddb57724ea 100644 --- a/chromium/mojo/edk/system/node_channel.cc +++ b/chromium/mojo/edk/system/node_channel.cc @@ -127,9 +127,15 @@ Channel::MessagePtr CreateMessage(MessageType type, } template <typename DataType> -void GetMessagePayload(const void* bytes, DataType** out_data) { +bool GetMessagePayload(const void* bytes, + size_t num_bytes, + DataType** out_data) { + static_assert(sizeof(DataType) > 0, "DataType must have non-zero size."); + if (num_bytes < sizeof(Header) + sizeof(DataType)) + return false; *out_data = reinterpret_cast<const DataType*>( static_cast<const char*>(bytes) + sizeof(Header)); + return true; } } // namespace @@ -166,8 +172,9 @@ void NodeChannel::Start() { #endif base::AutoLock lock(channel_lock_); - DCHECK(channel_); - channel_->Start(); + // ShutDown() may have already been called, in which case |channel_| is null. + if (channel_) + channel_->Start(); } void NodeChannel::ShutDown() { @@ -415,77 +422,93 @@ void NodeChannel::OnChannelMessage(const void* payload, } #endif // defined(OS_WIN) + + if (payload_size <= sizeof(Header)) { + delegate_->OnChannelError(remote_node_name_); + return; + } + const Header* header = static_cast<const Header*>(payload); switch (header->type) { case MessageType::ACCEPT_CHILD: { const AcceptChildData* data; - GetMessagePayload(payload, &data); - delegate_->OnAcceptChild(remote_node_name_, data->parent_name, - data->token); + if (GetMessagePayload(payload, payload_size, &data)) { + delegate_->OnAcceptChild(remote_node_name_, data->parent_name, + data->token); + return; + } break; } case MessageType::ACCEPT_PARENT: { const AcceptParentData* data; - GetMessagePayload(payload, &data); - delegate_->OnAcceptParent(remote_node_name_, data->token, - data->child_name); + if (GetMessagePayload(payload, payload_size, &data)) { + delegate_->OnAcceptParent(remote_node_name_, data->token, + data->child_name); + return; + } break; } case MessageType::ADD_BROKER_CLIENT: { const AddBrokerClientData* data; - GetMessagePayload(payload, &data); - ScopedPlatformHandle process_handle; + if (GetMessagePayload(payload, payload_size, &data)) { + ScopedPlatformHandle process_handle; #if defined(OS_WIN) - if (!handles || handles->size() != 1) { - DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; - break; - } - process_handle = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, - process_handle.release().handle); + if (!handles || handles->size() != 1) { + DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; + break; + } + process_handle = ScopedPlatformHandle(handles->at(0)); + handles->clear(); + delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, + process_handle.release().handle); #else - if (handles && handles->size() != 0) { - DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; - break; - } - delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, - data->process_handle); + if (handles && handles->size() != 0) { + DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; + break; + } + delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, + data->process_handle); #endif + return; + } break; } case MessageType::BROKER_CLIENT_ADDED: { const BrokerClientAddedData* data; - GetMessagePayload(payload, &data); - ScopedPlatformHandle broker_channel; - if (!handles || handles->size() != 1) { - DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; - break; + if (GetMessagePayload(payload, payload_size, &data)) { + ScopedPlatformHandle broker_channel; + if (!handles || handles->size() != 1) { + DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; + break; + } + broker_channel = ScopedPlatformHandle(handles->at(0)); + handles->clear(); + delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, + std::move(broker_channel)); + return; } - broker_channel = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, - std::move(broker_channel)); break; } case MessageType::ACCEPT_BROKER_CLIENT: { const AcceptBrokerClientData* data; - GetMessagePayload(payload, &data); - ScopedPlatformHandle broker_channel; - if (handles && handles->size() > 1) { - DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; - break; - } - if (handles && handles->size() == 1) { - broker_channel = ScopedPlatformHandle(handles->at(0)); - handles->clear(); + if (GetMessagePayload(payload, payload_size, &data)) { + ScopedPlatformHandle broker_channel; + if (handles && handles->size() > 1) { + DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; + break; + } + if (handles && handles->size() == 1) { + broker_channel = ScopedPlatformHandle(handles->at(0)); + handles->clear(); + } + delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, + std::move(broker_channel)); + return; } - delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, - std::move(broker_channel)); break; } @@ -495,44 +518,50 @@ void NodeChannel::OnChannelMessage(const void* payload, new Channel::Message(payload_size, num_handles)); message->SetHandles(std::move(handles)); memcpy(message->mutable_payload(), payload, payload_size); - delegate_->OnPortsMessage(std::move(message)); - break; + delegate_->OnPortsMessage(remote_node_name_, std::move(message)); + return; } case MessageType::REQUEST_PORT_MERGE: { const RequestPortMergeData* data; - GetMessagePayload(payload, &data); - - const char* token_data = reinterpret_cast<const char*>(data + 1); - const size_t token_size = payload_size - sizeof(*data) - sizeof(Header); - std::string token(token_data, token_size); - - delegate_->OnRequestPortMerge(remote_node_name_, - data->connector_port_name, token); + if (GetMessagePayload(payload, payload_size, &data)) { + // Don't accept an empty token. + size_t token_size = payload_size - sizeof(*data) - sizeof(Header); + if (token_size == 0) + break; + std::string token(reinterpret_cast<const char*>(data + 1), token_size); + delegate_->OnRequestPortMerge(remote_node_name_, + data->connector_port_name, token); + return; + } break; } case MessageType::REQUEST_INTRODUCTION: { const IntroductionData* data; - GetMessagePayload(payload, &data); - delegate_->OnRequestIntroduction(remote_node_name_, data->name); + if (GetMessagePayload(payload, payload_size, &data)) { + delegate_->OnRequestIntroduction(remote_node_name_, data->name); + return; + } break; } case MessageType::INTRODUCE: { const IntroductionData* data; - GetMessagePayload(payload, &data); - if (handles && handles->size() > 1) { - DLOG(ERROR) << "Dropping invalid introduction message."; - break; - } - ScopedPlatformHandle channel_handle; - if (handles && handles->size() == 1) { - channel_handle = ScopedPlatformHandle(handles->at(0)); - handles->clear(); + if (GetMessagePayload(payload, payload_size, &data)) { + if (handles && handles->size() > 1) { + DLOG(ERROR) << "Dropping invalid introduction message."; + break; + } + ScopedPlatformHandle channel_handle; + if (handles && handles->size() == 1) { + channel_handle = ScopedPlatformHandle(handles->at(0)); + handles->clear(); + } + delegate_->OnIntroduce(remote_node_name_, data->name, + std::move(channel_handle)); + return; } - delegate_->OnIntroduce(remote_node_name_, data->name, - std::move(channel_handle)); break; } @@ -544,45 +573,50 @@ void NodeChannel::OnChannelMessage(const void* payload, from_process = remote_process_handle_; } const RelayPortsMessageData* data; - GetMessagePayload(payload, &data); - const void* message_start = data + 1; - Channel::MessagePtr message = Channel::Message::Deserialize( - message_start, payload_size - sizeof(Header) - sizeof(*data)); - if (!message) { - DLOG(ERROR) << "Dropping invalid relay message."; - break; - } -#if defined(OS_MACOSX) && !defined(OS_IOS) - message->SetHandles(std::move(handles)); - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (!relay) { - LOG(ERROR) << "Receiving mach ports without a port relay from " - << remote_node_name_ << ". Dropping message."; - break; - } - { - base::AutoLock lock(pending_mach_messages_lock_); - if (relay->port_provider()->TaskForPid(from_process) == - MACH_PORT_NULL) { - pending_relay_messages_.push( - std::make_pair(data->destination, std::move(message))); + if (GetMessagePayload(payload, payload_size, &data)) { + // Don't try to relay an empty message. + if (payload_size <= sizeof(Header) + sizeof(RelayPortsMessageData)) + break; + + const void* message_start = data + 1; + Channel::MessagePtr message = Channel::Message::Deserialize( + message_start, payload_size - sizeof(Header) - sizeof(*data)); + if (!message) { + DLOG(ERROR) << "Dropping invalid relay message."; + break; + } + #if defined(OS_MACOSX) && !defined(OS_IOS) + message->SetHandles(std::move(handles)); + MachPortRelay* relay = delegate_->GetMachPortRelay(); + if (!relay) { + LOG(ERROR) << "Receiving mach ports without a port relay from " + << remote_node_name_ << ". Dropping message."; break; } + { + base::AutoLock lock(pending_mach_messages_lock_); + if (relay->port_provider()->TaskForPid(from_process) == + MACH_PORT_NULL) { + pending_relay_messages_.push( + std::make_pair(data->destination, std::move(message))); + break; + } + } + #endif + delegate_->OnRelayPortsMessage(remote_node_name_, from_process, + data->destination, std::move(message)); + return; } -#endif - delegate_->OnRelayPortsMessage(remote_node_name_, from_process, - data->destination, std::move(message)); break; } #endif default: - DLOG(ERROR) << "Received unknown message type " - << static_cast<uint32_t>(header->type) << " from node " - << remote_node_name_; - delegate_->OnChannelError(remote_node_name_); break; } + + DLOG(ERROR) << "Received invalid message. Closing channel."; + delegate_->OnChannelError(remote_node_name_); } void NodeChannel::OnChannelError() { diff --git a/chromium/mojo/edk/system/node_channel.h b/chromium/mojo/edk/system/node_channel.h index c8a97caf5e3..1aeccda10aa 100644 --- a/chromium/mojo/edk/system/node_channel.h +++ b/chromium/mojo/edk/system/node_channel.h @@ -53,7 +53,8 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>, virtual void OnAcceptBrokerClient(const ports::NodeName& from_node, const ports::NodeName& broker_name, ScopedPlatformHandle broker_channel) = 0; - virtual void OnPortsMessage(Channel::MessagePtr message) = 0; + virtual void OnPortsMessage(const ports::NodeName& from_node, + Channel::MessagePtr message) = 0; virtual void OnRequestPortMerge(const ports::NodeName& from_node, const ports::PortName& connector_port_name, const std::string& token) = 0; diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/edk/system/node_controller.cc index 58c87e24e36..40c57eeac58 100644 --- a/chromium/mojo/edk/system/node_controller.cc +++ b/chromium/mojo/edk/system/node_controller.cc @@ -786,20 +786,28 @@ void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node, DVLOG(1) << "Child " << name_ << " accepted by broker " << broker_name; } -void NodeController::OnPortsMessage(Channel::MessagePtr channel_message) { +void NodeController::OnPortsMessage(const ports::NodeName& from_node, + Channel::MessagePtr channel_message) { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); void* data; size_t num_data_bytes; NodeChannel::GetPortsMessageData( channel_message.get(), &data, &num_data_bytes); + if (!num_data_bytes) { + DropPeer(from_node); + return; + } size_t num_header_bytes, num_payload_bytes, num_ports_bytes; - ports::Message::Parse(data, - num_data_bytes, - &num_header_bytes, - &num_payload_bytes, - &num_ports_bytes); + if (!ports::Message::Parse(data, + num_data_bytes, + &num_header_bytes, + &num_payload_bytes, + &num_ports_bytes)) { + DropPeer(from_node); + return; + } CHECK(channel_message); ports::ScopedMessage message( @@ -928,7 +936,7 @@ void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, if (destination == name_) { // Great, we can deliver this message locally. - OnPortsMessage(std::move(message)); + OnPortsMessage(from_node, std::move(message)); return; } diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/edk/system/node_controller.h index c177f8f42db..463a72926f9 100644 --- a/chromium/mojo/edk/system/node_controller.h +++ b/chromium/mojo/edk/system/node_controller.h @@ -163,7 +163,8 @@ class NodeController : public ports::NodeDelegate, void OnAcceptBrokerClient(const ports::NodeName& from_node, const ports::NodeName& broker_name, ScopedPlatformHandle broker_channel) override; - void OnPortsMessage(Channel::MessagePtr message) override; + void OnPortsMessage(const ports::NodeName& from_node, + Channel::MessagePtr message) override; void OnRequestPortMerge(const ports::NodeName& from_node, const ports::PortName& connector_port_name, const std::string& token) override; diff --git a/chromium/mojo/edk/system/ports/message.cc b/chromium/mojo/edk/system/ports/message.cc index 2106c15671a..5d3c000a3a4 100644 --- a/chromium/mojo/edk/system/ports/message.cc +++ b/chromium/mojo/edk/system/ports/message.cc @@ -14,11 +14,13 @@ namespace edk { namespace ports { // static -void Message::Parse(const void* bytes, +bool Message::Parse(const void* bytes, size_t num_bytes, size_t* num_header_bytes, size_t* num_payload_bytes, size_t* num_ports_bytes) { + if (num_bytes < sizeof(EventHeader)) + return false; const EventHeader* header = static_cast<const EventHeader*>(bytes); switch (header->type) { case EventType::kUser: @@ -41,24 +43,32 @@ void Message::Parse(const void* bytes, *num_header_bytes = sizeof(EventHeader) + sizeof(MergePortEventData); break; default: - CHECK(false) << "Bad event type"; - return; + return false; } if (header->type == EventType::kUser) { + if (num_bytes < sizeof(EventHeader) + sizeof(UserEventData)) + return false; const UserEventData* event_data = reinterpret_cast<const UserEventData*>( reinterpret_cast<const char*>(header + 1)); + if (event_data->num_ports > std::numeric_limits<uint16_t>::max()) + return false; *num_header_bytes = sizeof(EventHeader) + sizeof(UserEventData) + event_data->num_ports * sizeof(PortDescriptor); *num_ports_bytes = event_data->num_ports * sizeof(PortName); + if (num_bytes < *num_header_bytes + *num_ports_bytes) + return false; *num_payload_bytes = num_bytes - *num_header_bytes - *num_ports_bytes; } else { + if (*num_header_bytes != num_bytes) + return false; *num_payload_bytes = 0; *num_ports_bytes = 0; - DCHECK_EQ(num_bytes, *num_header_bytes); } + + return true; } Message::Message(size_t num_payload_bytes, size_t num_ports) diff --git a/chromium/mojo/edk/system/ports/message.h b/chromium/mojo/edk/system/ports/message.h index df3b8f2ddbf..926ce752a84 100644 --- a/chromium/mojo/edk/system/ports/message.h +++ b/chromium/mojo/edk/system/ports/message.h @@ -26,8 +26,9 @@ class Message { public: virtual ~Message() {} - // Inspect the message at |bytes| and return the size of each section. - static void Parse(const void* bytes, + // Inspect the message at |bytes| and return the size of each section. Returns + // |false| if the message is malformed and |true| otherwise. + static bool Parse(const void* bytes, size_t num_bytes, size_t* num_header_bytes, size_t* num_payload_bytes, |
