summaryrefslogtreecommitdiff
path: root/chromium/mojo
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/mojo')
-rw-r--r--chromium/mojo/edk/system/broker_host_posix.cc20
-rw-r--r--chromium/mojo/edk/system/channel.cc49
-rw-r--r--chromium/mojo/edk/system/channel.h20
-rw-r--r--chromium/mojo/edk/system/channel_posix.cc64
-rw-r--r--chromium/mojo/edk/system/channel_win.cc20
-rw-r--r--chromium/mojo/edk/system/node_channel.cc228
-rw-r--r--chromium/mojo/edk/system/node_channel.h3
-rw-r--r--chromium/mojo/edk/system/node_controller.cc22
-rw-r--r--chromium/mojo/edk/system/node_controller.h3
-rw-r--r--chromium/mojo/edk/system/ports/message.cc18
-rw-r--r--chromium/mojo/edk/system/ports/message.h5
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,