transport_data.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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; 250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)COMPILE_ASSERT(kMaxSizePerPlatformHandle % 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::kMessageAlignment == 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0, 280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kMaxSizePerPlatformHandle_not_a_multiple_of_alignment); 290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const size_t 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TransportData::kMaxSerializedDispatcherSize; 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const size_t 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TransportData::kMaxSerializedDispatcherPlatformHandles; 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// static 360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)const size_t TransportData::kMaxPlatformHandles = 370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kMaxMessageNumHandles * kMaxSerializedDispatcherPlatformHandles; 380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// In additional to the header, for each attached (Mojo) handle there'll be a 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// handle table entry and serialized dispatcher data. 410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Note: This definition must follow the one for |kMaxPlatformHandles|; 420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// otherwise, we get a static initializer with gcc (but not clang). 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const size_t TransportData::kMaxBufferSize = 450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) sizeof(Header) + 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kMaxMessageNumHandles * 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) + 480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kMaxPlatformHandles * kMaxSizePerPlatformHandle; 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)struct TransportData::PrivateStructForCompileAsserts { 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The size of |Header| must be a multiple of the alignment. 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) COMPILE_ASSERT(sizeof(Header) % MessageInTransit::kMessageAlignment == 0, 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sizeof_MessageInTransit_Header_invalid); 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The maximum serialized dispatcher size must be a multiple of the alignment. 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) COMPILE_ASSERT(kMaxSerializedDispatcherSize % 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::kMessageAlignment == 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0, 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMaxSerializedDispatcherSize_not_a_multiple_of_alignment); 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The size of |HandleTableEntry| must be a multiple of the alignment. 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) COMPILE_ASSERT(sizeof(HandleTableEntry) % 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::kMessageAlignment == 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0, 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sizeof_MessageInTransit_HandleTableEntry_invalid); 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Channel* channel) { 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(dispatchers); 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(channel); 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = dispatchers->size(); 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(num_handles, 0u); 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The offset to the start of the (Mojo) handle table. 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t handle_table_start_offset = sizeof(Header); 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The offset to the start of the serialized dispatcher data. 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t serialized_dispatcher_start_offset = 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table_start_offset + num_handles * sizeof(HandleTableEntry); 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The estimated size of the secondary buffer. We compute this estimate below. 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // It must be at least as big as the (eventual) actual size. 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t estimated_size = serialized_dispatcher_start_offset; 840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t estimated_num_platform_handles = 0; 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<size_t> all_max_sizes(num_handles); 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<size_t> all_max_platform_handles(num_handles); 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t max_size = 0; 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t max_platform_handles = 0; 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Dispatcher::TransportDataAccess::StartSerialize( 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatcher, channel, &max_size, &max_platform_handles); 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(max_size, kMaxSerializedDispatcherSize); 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(estimated_size, kMaxBufferSize); 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles); 1010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_num_platform_handles += max_platform_handles; 1020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(estimated_num_platform_handles, kMaxPlatformHandles); 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_sizes[i] = max_size; 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_platform_handles[i] = max_platform_handles; 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t size_per_platform_handle = 0; 1120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (estimated_num_platform_handles > 0) { 1130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_per_platform_handle = channel->GetSerializedPlatformHandleSize(); 1140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle); 1150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_size += estimated_num_platform_handles * size_per_platform_handle; 1160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size); 1170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_LE(estimated_size, kMaxBufferSize); 1180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_.reset(static_cast<char*>( 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment))); 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Entirely clear out the secondary buffer, since then we won't have to worry 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // about clearing padding or unused space (e.g., if a dispatcher fails to 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // serialize). 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) memset(buffer_.get(), 0, estimated_size); 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (estimated_num_platform_handles > 0) { 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!platform_handles_); 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) platform_handles_.reset(new embedder::PlatformHandleVector()); 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Header* header = reinterpret_cast<Header*>(buffer_.get()); 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) header->num_handles = static_cast<uint32_t>(num_handles); 1340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // (Okay to leave |platform_handle_table_offset|, |num_platform_handles|, and 1350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // |unused| be zero; we'll set the former two later if necessary.) 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>( 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_.get() + handle_table_start_offset); 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t current_offset = serialized_dispatcher_start_offset; 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Dispatcher* dispatcher = (*dispatchers)[i].get(); 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!dispatcher) { 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) COMPILE_ASSERT(Dispatcher::kTypeUnknown == 0, 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) value_of_Dispatcher_kTypeUnknown_must_be_zero); 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) continue; 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t old_platform_handles_size = 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) platform_handles_ ? platform_handles_->size() : 0; 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void* destination = buffer_.get() + current_offset; 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t actual_size = 0; 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (Dispatcher::TransportDataAccess::EndSerializeAndClose( 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatcher, 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel, 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) destination, 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &actual_size, 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) platform_handles_.get())) { 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].offset = static_cast<uint32_t>(current_offset); 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) handle_table[i].size = static_cast<uint32_t>(actual_size); 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// (Okay to not set |unused| since we cleared the entire buffer.) 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if DCHECK_IS_ON 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(actual_size, all_max_sizes[i]); 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LE(platform_handles_ 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ? (platform_handles_->size() - old_platform_handles_size) 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : 0, 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) all_max_platform_handles[i]); 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else { 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Nothing to do on failure, since |buffer_| was cleared, and 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |kTypeUnknown| is zero. The handle was simply closed. 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) LOG(ERROR) << "Failed to serialize handle to remote message pipe"; 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_offset += MessageInTransit::RoundUpMessageAlignment(actual_size); 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(current_offset, estimated_size); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0, 1820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) estimated_num_platform_handles); 1830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 1840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 1850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (platform_handles_ && platform_handles_->size() > 0) { 1860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) header->platform_handle_table_offset = 1870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<uint32_t>(current_offset); 1880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) header->num_platform_handles = 1890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<uint32_t>(platform_handles_->size()); 1900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) current_offset += platform_handles_->size() * size_per_platform_handle; 1910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) current_offset = MessageInTransit::RoundUpMessageAlignment(current_offset); 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // There's no aligned realloc, so it's no good way to release unused space (if 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // we overshot our estimated space requirements). 196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_size_ = current_offset; 197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |dispatchers_| will be destroyed as it goes out of scope. 199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_POSIX) 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TransportData::TransportData( 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::ScopedPlatformHandleVectorPtr platform_handles) 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : buffer_size_(sizeof(Header)), platform_handles_(platform_handles.Pass()) { 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_.reset(static_cast<char*>( 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment))); 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memset(buffer_.get(), 0, buffer_size_); 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // defined(OS_POSIX) 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TransportData::~TransportData() { 212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* TransportData::ValidateBuffer( 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t serialized_platform_handle_size, 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void* buffer, 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t buffer_size) { 219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(buffer); 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(buffer_size, 0u); 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Always make sure that the buffer size is sane; if it's not, someone's 223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // messing with us. 224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (buffer_size < sizeof(Header) || buffer_size > kMaxBufferSize || 225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buffer_size % MessageInTransit::kMessageAlignment != 0) 226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Invalid message secondary buffer size"; 227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Header* header = static_cast<const Header*>(buffer); 229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = header->num_handles; 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(OS_POSIX) 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // On POSIX, we send control messages with platform handles (but no handles) 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // attached (see the comments for 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |TransportData(embedder::ScopedPlatformHandleVectorPtr)|. (This check isn't 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // important security-wise anyway.) 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (num_handles == 0) 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message has no handles attached, but secondary buffer present"; 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Sanity-check |num_handles| (before multiplying it against anything). 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (num_handles > kMaxMessageNumHandles) 242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message handle payload too large"; 243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) 245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return "Message secondary buffer too small"; 246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->num_platform_handles == 0) { 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Then |platform_handle_table_offset| should also be zero. 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset != 0) { 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "Message has no handles attached, but platform handle table " 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "present"; 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |num_handles| has already been validated, so the multiplication is okay. 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->num_platform_handles > 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) num_handles * kMaxSerializedDispatcherPlatformHandles) 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return "Message has too many platform handles attached"; 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static const char kInvalidPlatformHandleTableOffset[] = 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Message has invalid platform handle table offset"; 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This doesn't check that the platform handle table doesn't alias other 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // stuff, but it doesn't matter, since it's all read-only. 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset % 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::kMessageAlignment != 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0) 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ">" instead of ">=" since the size per handle may be zero. 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset > buffer_size) 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We already checked |platform_handle_table_offset| and 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |num_platform_handles|, so the addition and multiplication are okay. 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (header->platform_handle_table_offset + 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) header->num_platform_handles * serialized_platform_handle_size > 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_size) 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kInvalidPlatformHandleTableOffset; 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const HandleTableEntry* handle_table = 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reinterpret_cast<const HandleTableEntry*>( 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<const char*>(buffer) + sizeof(Header)); 283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static const char kInvalidSerializedDispatcher[] = 284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "Message contains invalid serialized dispatcher"; 285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t offset = handle_table[i].offset; 287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (offset % MessageInTransit::kMessageAlignment != 0) 288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t size = handle_table[i].size; 291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (size > kMaxSerializedDispatcherSize || size > buffer_size) 292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: This is an overflow-safe check for |offset + size > buffer_size| 295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // (we know that |size <= buffer_size| from the previous check). 296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (offset > buffer_size - size) 297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return kInvalidSerializedDispatcher; 298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return NULL; 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t* num_platform_handles, 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void** platform_handle_table) { 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(transport_data_buffer); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(num_platform_handles); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(platform_handle_table); 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Header* header = static_cast<const Header*>(transport_data_buffer); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *num_platform_handles = header->num_platform_handles; 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *platform_handle_table = static_cast<const char*>(transport_data_buffer) + 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) header->platform_handle_table_offset; 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchers( 319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const void* buffer, 320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t buffer_size, 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::ScopedPlatformHandleVectorPtr platform_handles, 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Channel* channel) { 323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(buffer); 324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_GT(buffer_size, 0u); 325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(channel); 326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Header* header = static_cast<const Header*>(buffer); 328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const size_t num_handles = header->num_handles; 329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector(num_handles)); 330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const HandleTableEntry* handle_table = 332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reinterpret_cast<const HandleTableEntry*>( 333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<const char*>(buffer) + sizeof(Header)); 334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (size_t i = 0; i < num_handles; i++) { 335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t offset = handle_table[i].offset; 336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t size = handle_table[i].size; 337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Should already have been checked by |ValidateBuffer()|: 338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(offset % MessageInTransit::kMessageAlignment, 0u); 339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(offset, buffer_size); 340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_LE(offset + size, buffer_size); 341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const void* source = static_cast<const char*>(buffer) + offset; 343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) channel, handle_table[i].type, source, size, platform_handles.get()); 345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return dispatchers.Pass(); 348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace system 351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace mojo 352