1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/transport_data.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <string.h> 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/compiler_specific.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/logging.h" 110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "mojo/system/channel.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/constants.h" 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/message_in_transit.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace mojo { 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace system { 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// The maximum amount of space needed per platform handle. 190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always 200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// return a value which is at most this. This is only used to calculate 210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// |TransportData::kMaxBufferSize|. This value should be a multiple of the 220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// alignment in order to simplify calculations, even though the actual amount of 230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// space needed need not be a multiple of the alignment. 240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)const size_t kMaxSizePerPlatformHandle = 8; 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment == 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "kMaxSizePerPlatformHandle not a multiple of alignment"); 280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const size_t 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TransportData::kMaxSerializedDispatcherSize; 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const size_t 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TransportData::kMaxSerializedDispatcherPlatformHandles; 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// static 350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)const size_t TransportData::kMaxPlatformHandles = 360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kMaxMessageNumHandles * kMaxSerializedDispatcherPlatformHandles; 370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// In additional to the header, for each attached (Mojo) handle there'll be a 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// handle table entry and serialized dispatcher data. 400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Note: This definition must follow the one for |kMaxPlatformHandles|; 410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// otherwise, we get a static initializer with gcc (but not clang). 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const size_t TransportData::kMaxBufferSize = 440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) sizeof(Header) + 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kMaxMessageNumHandles * 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) + 470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kMaxPlatformHandles * kMaxSizePerPlatformHandle; 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)struct TransportData::PrivateStructForCompileAsserts { 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0, 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "sizeof(MessageInTransit::Header) not a multiple of alignment"); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_assert(kMaxSerializedDispatcherSize % 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessageInTransit::kMessageAlignment == 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "kMaxSerializedDispatcherSize not a multiple of alignment"); 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_assert(sizeof(HandleTableEntry) % 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessageInTransit::kMessageAlignment == 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "sizeof(MessageInTransit::HandleTableEntry) not a multiple of " 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "alignment"); 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Channel* channel) { 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(dispatchers); 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(channel); 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = dispatchers->size(); 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(num_handles, 0u); 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The offset to the start of the (Mojo) handle table. 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t handle_table_start_offset = sizeof(Header); 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The offset to the start of the serialized dispatcher data. 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t serialized_dispatcher_start_offset = 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table_start_offset + num_handles * sizeof(HandleTableEntry); 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The estimated size of the secondary buffer. We compute this estimate below. 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // It must be at least as big as the (eventual) actual size. 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t estimated_size = serialized_dispatcher_start_offset; 790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t estimated_num_platform_handles = 0; 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<size_t> all_max_sizes(num_handles); 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<size_t> all_max_platform_handles(num_handles); 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t max_size = 0; 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t max_platform_handles = 0; 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Dispatcher::TransportDataAccess::StartSerialize( 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatcher, channel, &max_size, &max_platform_handles); 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(max_size, kMaxSerializedDispatcherSize); 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(estimated_size, kMaxBufferSize); 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles); 960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_num_platform_handles += max_platform_handles; 970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(estimated_num_platform_handles, kMaxPlatformHandles); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_sizes[i] = max_size; 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_platform_handles[i] = max_platform_handles; 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t size_per_platform_handle = 0; 1070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (estimated_num_platform_handles > 0) { 1080de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_per_platform_handle = channel->GetSerializedPlatformHandleSize(); 1090de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle); 1100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_size += estimated_num_platform_handles * size_per_platform_handle; 1110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size); 1120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(estimated_size, kMaxBufferSize); 1130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_.reset(static_cast<char*>( 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment))); 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Entirely clear out the secondary buffer, since then we won't have to worry 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // about clearing padding or unused space (e.g., if a dispatcher fails to 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // serialize). 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) memset(buffer_.get(), 0, estimated_size); 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (estimated_num_platform_handles > 0) { 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!platform_handles_); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) platform_handles_.reset(new embedder::PlatformHandleVector()); 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Header* header = reinterpret_cast<Header*>(buffer_.get()); 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) header->num_handles = static_cast<uint32_t>(num_handles); 1290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // (Okay to leave |platform_handle_table_offset|, |num_platform_handles|, and 1300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // |unused| be zero; we'll set the former two later if necessary.) 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>( 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_.get() + handle_table_start_offset); 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t current_offset = serialized_dispatcher_start_offset; 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Dispatcher* dispatcher = (*dispatchers)[i].get(); 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!dispatcher) { 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_assert(Dispatcher::kTypeUnknown == 0, 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Value of Dispatcher::kTypeUnknown must be 0"); 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) continue; 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t old_platform_handles_size = 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) platform_handles_ ? platform_handles_->size() : 0; 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void* destination = buffer_.get() + current_offset; 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t actual_size = 0; 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (Dispatcher::TransportDataAccess::EndSerializeAndClose( 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatcher, 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel, 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) destination, 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &actual_size, 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) platform_handles_.get())) { 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].offset = static_cast<uint32_t>(current_offset); 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].size = static_cast<uint32_t>(actual_size); 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// (Okay to not set |unused| since we cleared the entire buffer.) 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(actual_size, all_max_sizes[i]); 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LE(platform_handles_ 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ? (platform_handles_->size() - old_platform_handles_size) 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : 0, 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_platform_handles[i]); 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else { 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Nothing to do on failure, since |buffer_| was cleared, and 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |kTypeUnknown| is zero. The handle was simply closed. 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) LOG(ERROR) << "Failed to serialize handle to remote message pipe"; 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_offset += MessageInTransit::RoundUpMessageAlignment(actual_size); 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(current_offset, estimated_size); 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0, 1770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_num_platform_handles); 1780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 1800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (platform_handles_ && platform_handles_->size() > 0) { 1810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) header->platform_handle_table_offset = 1820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<uint32_t>(current_offset); 1830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) header->num_platform_handles = 1840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<uint32_t>(platform_handles_->size()); 1850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) current_offset += platform_handles_->size() * size_per_platform_handle; 1860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) current_offset = MessageInTransit::RoundUpMessageAlignment(current_offset); 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // There's no aligned realloc, so it's no good way to release unused space (if 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // we overshot our estimated space requirements). 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_size_ = current_offset; 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |dispatchers_| will be destroyed as it goes out of scope. 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_POSIX) 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TransportData::TransportData( 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::ScopedPlatformHandleVectorPtr platform_handles) 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : buffer_size_(sizeof(Header)), platform_handles_(platform_handles.Pass()) { 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_.reset(static_cast<char*>( 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment))); 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memset(buffer_.get(), 0, buffer_size_); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // defined(OS_POSIX) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TransportData::~TransportData() { 207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* TransportData::ValidateBuffer( 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t serialized_platform_handle_size, 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void* buffer, 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t buffer_size) { 214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(buffer); 215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(buffer_size, 0u); 216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Always make sure that the buffer size is sane; if it's not, someone's 218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // messing with us. 219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (buffer_size < sizeof(Header) || buffer_size > kMaxBufferSize || 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_size % MessageInTransit::kMessageAlignment != 0) 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Invalid message secondary buffer size"; 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Header* header = static_cast<const Header*>(buffer); 224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = header->num_handles; 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(OS_POSIX) 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // On POSIX, we send control messages with platform handles (but no handles) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // attached (see the comments for 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |TransportData(embedder::ScopedPlatformHandleVectorPtr)|. (This check isn't 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // important security-wise anyway.) 231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (num_handles == 0) 232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message has no handles attached, but secondary buffer present"; 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Sanity-check |num_handles| (before multiplying it against anything). 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (num_handles > kMaxMessageNumHandles) 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message handle payload too large"; 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message secondary buffer too small"; 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->num_platform_handles == 0) { 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Then |platform_handle_table_offset| should also be zero. 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset != 0) { 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "Message has no handles attached, but platform handle table " 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "present"; 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |num_handles| has already been validated, so the multiplication is okay. 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->num_platform_handles > 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) num_handles * kMaxSerializedDispatcherPlatformHandles) 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return "Message has too many platform handles attached"; 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static const char kInvalidPlatformHandleTableOffset[] = 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Message has invalid platform handle table offset"; 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This doesn't check that the platform handle table doesn't alias other 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // stuff, but it doesn't matter, since it's all read-only. 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset % 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::kMessageAlignment != 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0) 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ">" instead of ">=" since the size per handle may be zero. 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset > buffer_size) 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We already checked |platform_handle_table_offset| and 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |num_platform_handles|, so the addition and multiplication are okay. 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset + 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) header->num_platform_handles * serialized_platform_handle_size > 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_size) 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const HandleTableEntry* handle_table = 276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reinterpret_cast<const HandleTableEntry*>( 277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<const char*>(buffer) + sizeof(Header)); 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static const char kInvalidSerializedDispatcher[] = 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "Message contains invalid serialized dispatcher"; 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t offset = handle_table[i].offset; 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (offset % MessageInTransit::kMessageAlignment != 0) 283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t size = handle_table[i].size; 286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (size > kMaxSerializedDispatcherSize || size > buffer_size) 287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: This is an overflow-safe check for |offset + size > buffer_size| 290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // (we know that |size <= buffer_size| from the previous check). 291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (offset > buffer_size - size) 292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return nullptr; 296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t* num_platform_handles, 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void** platform_handle_table) { 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(transport_data_buffer); 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(num_platform_handles); 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(platform_handle_table); 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Header* header = static_cast<const Header*>(transport_data_buffer); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *num_platform_handles = header->num_platform_handles; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *platform_handle_table = static_cast<const char*>(transport_data_buffer) + 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) header->platform_handle_table_offset; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchers( 314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const void* buffer, 315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t buffer_size, 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::ScopedPlatformHandleVectorPtr platform_handles, 317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Channel* channel) { 318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(buffer); 319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(buffer_size, 0u); 320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(channel); 321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Header* header = static_cast<const Header*>(buffer); 323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = header->num_handles; 324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector(num_handles)); 325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const HandleTableEntry* handle_table = 327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reinterpret_cast<const HandleTableEntry*>( 328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<const char*>(buffer) + sizeof(Header)); 329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t offset = handle_table[i].offset; 331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t size = handle_table[i].size; 332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Should already have been checked by |ValidateBuffer()|: 333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(offset % MessageInTransit::kMessageAlignment, 0u); 334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(offset, buffer_size); 335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(offset + size, buffer_size); 336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const void* source = static_cast<const char*>(buffer) + offset; 338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) channel, handle_table[i].type, source, size, platform_handles.get()); 340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return dispatchers.Pass(); 343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace system 346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace mojo 347