Index: mojo/edk/system/channel.cc |
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc |
index c8d693176c917620207a73335d47f7634eb1aab3..2976a21b8a4b2d5b4a8e289fb0748991998bef30 100644 |
--- a/mojo/edk/system/channel.cc |
+++ b/mojo/edk/system/channel.cc |
@@ -164,14 +164,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) { |
Anand Mistry (off Chromium)
2016/05/16 04:27:48
These only protect against 0-byte memcpy's, which
Ken Rockot(use gerrit already)
2016/05/16 04:39:14
Yeah - mostly I'm just uncomfortable with ever pas
|
+ // 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; |
@@ -530,9 +536,12 @@ 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) |
Anand Mistry (off Chromium)
2016/05/16 04:27:48
Can you add a LOG(ERROR) here, similar to the one
Ken Rockot(use gerrit already)
2016/05/16 04:39:14
Done - though this can certainly happen with a mal
Anand Mistry (off Chromium)
2016/05/16 04:45:50
Thanks. I'm assuming malicious input is not normal
|
+ 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*>( |
@@ -543,8 +552,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; |
@@ -553,8 +565,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)); |
@@ -573,5 +587,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 |