| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/edk/system/transport_data.h" | 5 #include "mojo/edk/system/transport_data.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "mojo/edk/system/channel.h" | 11 #include "mojo/edk/system/channel.h" |
| 12 #include "mojo/edk/system/constants.h" | 12 #include "mojo/edk/system/configuration.h" |
| 13 #include "mojo/edk/system/message_in_transit.h" | 13 #include "mojo/edk/system/message_in_transit.h" |
| 14 | 14 |
| 15 namespace mojo { | 15 namespace mojo { |
| 16 namespace system { | 16 namespace system { |
| 17 | 17 |
| 18 // The maximum amount of space needed per platform handle. | 18 // The maximum amount of space needed per platform handle. |
| 19 // (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always | 19 // (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always |
| 20 // return a value which is at most this. This is only used to calculate | 20 // return a value which is at most this. This is only used to calculate |
| 21 // |TransportData::kMaxBufferSize|. This value should be a multiple of the | 21 // |TransportData::kMaxBufferSize|. This value should be a multiple of the |
| 22 // alignment in order to simplify calculations, even though the actual amount of | 22 // alignment in order to simplify calculations, even though the actual amount of |
| 23 // space needed need not be a multiple of the alignment. | 23 // space needed need not be a multiple of the alignment. |
| 24 const size_t kMaxSizePerPlatformHandle = 8; | 24 const size_t kMaxSizePerPlatformHandle = 8; |
| 25 static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment == | 25 static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment == |
| 26 0, | 26 0, |
| 27 "kMaxSizePerPlatformHandle not a multiple of alignment"); | 27 "kMaxSizePerPlatformHandle not a multiple of alignment"); |
| 28 | 28 |
| 29 STATIC_CONST_MEMBER_DEFINITION const size_t | 29 STATIC_CONST_MEMBER_DEFINITION const size_t |
| 30 TransportData::kMaxSerializedDispatcherSize; | 30 TransportData::kMaxSerializedDispatcherSize; |
| 31 STATIC_CONST_MEMBER_DEFINITION const size_t | 31 STATIC_CONST_MEMBER_DEFINITION const size_t |
| 32 TransportData::kMaxSerializedDispatcherPlatformHandles; | 32 TransportData::kMaxSerializedDispatcherPlatformHandles; |
| 33 | 33 |
| 34 // static | 34 // static |
| 35 const size_t TransportData::kMaxPlatformHandles = | 35 size_t TransportData::GetMaxBufferSize() { |
| 36 kMaxMessageNumHandles * kMaxSerializedDispatcherPlatformHandles; | 36 // In additional to the header, for each attached (Mojo) handle there'll be a |
| 37 // handle table entry and serialized dispatcher data. |
| 38 return sizeof(Header) + |
| 39 GetConfiguration().max_message_num_handles * |
| 40 (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) + |
| 41 GetMaxPlatformHandles() * kMaxSizePerPlatformHandle; |
| 42 } |
| 37 | 43 |
| 38 // In additional to the header, for each attached (Mojo) handle there'll be a | |
| 39 // handle table entry and serialized dispatcher data. | |
| 40 // Note: This definition must follow the one for |kMaxPlatformHandles|; | |
| 41 // otherwise, we get a static initializer with gcc (but not clang). | |
| 42 // static | 44 // static |
| 43 const size_t TransportData::kMaxBufferSize = | 45 size_t TransportData::GetMaxPlatformHandles() { |
| 44 sizeof(Header) + | 46 return GetConfiguration().max_message_num_handles * |
| 45 kMaxMessageNumHandles * | 47 kMaxSerializedDispatcherPlatformHandles; |
| 46 (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) + | 48 } |
| 47 kMaxPlatformHandles * kMaxSizePerPlatformHandle; | |
| 48 | 49 |
| 49 struct TransportData::PrivateStructForCompileAsserts { | 50 struct TransportData::PrivateStructForCompileAsserts { |
| 50 static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0, | 51 static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0, |
| 51 "sizeof(MessageInTransit::Header) not a multiple of alignment"); | 52 "sizeof(MessageInTransit::Header) not a multiple of alignment"); |
| 52 static_assert(kMaxSerializedDispatcherSize % | 53 static_assert(kMaxSerializedDispatcherSize % |
| 53 MessageInTransit::kMessageAlignment == | 54 MessageInTransit::kMessageAlignment == |
| 54 0, | 55 0, |
| 55 "kMaxSerializedDispatcherSize not a multiple of alignment"); | 56 "kMaxSerializedDispatcherSize not a multiple of alignment"); |
| 56 static_assert(sizeof(HandleTableEntry) % | 57 static_assert(sizeof(HandleTableEntry) % |
| 57 MessageInTransit::kMessageAlignment == | 58 MessageInTransit::kMessageAlignment == |
| (...skipping 25 matching lines...) Expand all Loading... |
| 83 #endif | 84 #endif |
| 84 for (size_t i = 0; i < num_handles; i++) { | 85 for (size_t i = 0; i < num_handles; i++) { |
| 85 if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { | 86 if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { |
| 86 size_t max_size = 0; | 87 size_t max_size = 0; |
| 87 size_t max_platform_handles = 0; | 88 size_t max_platform_handles = 0; |
| 88 Dispatcher::TransportDataAccess::StartSerialize( | 89 Dispatcher::TransportDataAccess::StartSerialize( |
| 89 dispatcher, channel, &max_size, &max_platform_handles); | 90 dispatcher, channel, &max_size, &max_platform_handles); |
| 90 | 91 |
| 91 DCHECK_LE(max_size, kMaxSerializedDispatcherSize); | 92 DCHECK_LE(max_size, kMaxSerializedDispatcherSize); |
| 92 estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); | 93 estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); |
| 93 DCHECK_LE(estimated_size, kMaxBufferSize); | 94 DCHECK_LE(estimated_size, GetMaxBufferSize()); |
| 94 | 95 |
| 95 DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles); | 96 DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles); |
| 96 estimated_num_platform_handles += max_platform_handles; | 97 estimated_num_platform_handles += max_platform_handles; |
| 97 DCHECK_LE(estimated_num_platform_handles, kMaxPlatformHandles); | 98 DCHECK_LE(estimated_num_platform_handles, GetMaxPlatformHandles()); |
| 98 | 99 |
| 99 #if DCHECK_IS_ON | 100 #if DCHECK_IS_ON |
| 100 all_max_sizes[i] = max_size; | 101 all_max_sizes[i] = max_size; |
| 101 all_max_platform_handles[i] = max_platform_handles; | 102 all_max_platform_handles[i] = max_platform_handles; |
| 102 #endif | 103 #endif |
| 103 } | 104 } |
| 104 } | 105 } |
| 105 | 106 |
| 106 size_t size_per_platform_handle = 0; | 107 size_t size_per_platform_handle = 0; |
| 107 if (estimated_num_platform_handles > 0) { | 108 if (estimated_num_platform_handles > 0) { |
| 108 size_per_platform_handle = channel->GetSerializedPlatformHandleSize(); | 109 size_per_platform_handle = channel->GetSerializedPlatformHandleSize(); |
| 109 DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle); | 110 DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle); |
| 110 estimated_size += estimated_num_platform_handles * size_per_platform_handle; | 111 estimated_size += estimated_num_platform_handles * size_per_platform_handle; |
| 111 estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size); | 112 estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size); |
| 112 DCHECK_LE(estimated_size, kMaxBufferSize); | 113 DCHECK_LE(estimated_size, GetMaxBufferSize()); |
| 113 } | 114 } |
| 114 | 115 |
| 115 buffer_.reset(static_cast<char*>( | 116 buffer_.reset(static_cast<char*>( |
| 116 base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment))); | 117 base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment))); |
| 117 // Entirely clear out the secondary buffer, since then we won't have to worry | 118 // Entirely clear out the secondary buffer, since then we won't have to worry |
| 118 // about clearing padding or unused space (e.g., if a dispatcher fails to | 119 // about clearing padding or unused space (e.g., if a dispatcher fails to |
| 119 // serialize). | 120 // serialize). |
| 120 memset(buffer_.get(), 0, estimated_size); | 121 memset(buffer_.get(), 0, estimated_size); |
| 121 | 122 |
| 122 if (estimated_num_platform_handles > 0) { | 123 if (estimated_num_platform_handles > 0) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 141 } | 142 } |
| 142 | 143 |
| 143 #if DCHECK_IS_ON | 144 #if DCHECK_IS_ON |
| 144 size_t old_platform_handles_size = | 145 size_t old_platform_handles_size = |
| 145 platform_handles_ ? platform_handles_->size() : 0; | 146 platform_handles_ ? platform_handles_->size() : 0; |
| 146 #endif | 147 #endif |
| 147 | 148 |
| 148 void* destination = buffer_.get() + current_offset; | 149 void* destination = buffer_.get() + current_offset; |
| 149 size_t actual_size = 0; | 150 size_t actual_size = 0; |
| 150 if (Dispatcher::TransportDataAccess::EndSerializeAndClose( | 151 if (Dispatcher::TransportDataAccess::EndSerializeAndClose( |
| 151 dispatcher, | 152 dispatcher, channel, destination, &actual_size, |
| 152 channel, | |
| 153 destination, | |
| 154 &actual_size, | |
| 155 platform_handles_.get())) { | 153 platform_handles_.get())) { |
| 156 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); | 154 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); |
| 157 handle_table[i].offset = static_cast<uint32_t>(current_offset); | 155 handle_table[i].offset = static_cast<uint32_t>(current_offset); |
| 158 handle_table[i].size = static_cast<uint32_t>(actual_size); | 156 handle_table[i].size = static_cast<uint32_t>(actual_size); |
| 159 // (Okay to not set |unused| since we cleared the entire buffer.) | 157 // (Okay to not set |unused| since we cleared the entire buffer.) |
| 160 | 158 |
| 161 #if DCHECK_IS_ON | 159 #if DCHECK_IS_ON |
| 162 DCHECK_LE(actual_size, all_max_sizes[i]); | 160 DCHECK_LE(actual_size, all_max_sizes[i]); |
| 163 DCHECK_LE(platform_handles_ | 161 DCHECK_LE(platform_handles_ |
| 164 ? (platform_handles_->size() - old_platform_handles_size) | 162 ? (platform_handles_->size() - old_platform_handles_size) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 // static | 207 // static |
| 210 const char* TransportData::ValidateBuffer( | 208 const char* TransportData::ValidateBuffer( |
| 211 size_t serialized_platform_handle_size, | 209 size_t serialized_platform_handle_size, |
| 212 const void* buffer, | 210 const void* buffer, |
| 213 size_t buffer_size) { | 211 size_t buffer_size) { |
| 214 DCHECK(buffer); | 212 DCHECK(buffer); |
| 215 DCHECK_GT(buffer_size, 0u); | 213 DCHECK_GT(buffer_size, 0u); |
| 216 | 214 |
| 217 // Always make sure that the buffer size is sane; if it's not, someone's | 215 // Always make sure that the buffer size is sane; if it's not, someone's |
| 218 // messing with us. | 216 // messing with us. |
| 219 if (buffer_size < sizeof(Header) || buffer_size > kMaxBufferSize || | 217 if (buffer_size < sizeof(Header) || buffer_size > GetMaxBufferSize() || |
| 220 buffer_size % MessageInTransit::kMessageAlignment != 0) | 218 buffer_size % MessageInTransit::kMessageAlignment != 0) |
| 221 return "Invalid message secondary buffer size"; | 219 return "Invalid message secondary buffer size"; |
| 222 | 220 |
| 223 const Header* header = static_cast<const Header*>(buffer); | 221 const Header* header = static_cast<const Header*>(buffer); |
| 224 const size_t num_handles = header->num_handles; | 222 const size_t num_handles = header->num_handles; |
| 225 | 223 |
| 226 #if !defined(OS_POSIX) | 224 #if !defined(OS_POSIX) |
| 227 // On POSIX, we send control messages with platform handles (but no handles) | 225 // On POSIX, we send control messages with platform handles (but no handles) |
| 228 // attached (see the comments for | 226 // attached (see the comments for |
| 229 // |TransportData(embedder::ScopedPlatformHandleVectorPtr)|. (This check isn't | 227 // |TransportData(embedder::ScopedPlatformHandleVectorPtr)|. (This check isn't |
| 230 // important security-wise anyway.) | 228 // important security-wise anyway.) |
| 231 if (num_handles == 0) | 229 if (num_handles == 0) |
| 232 return "Message has no handles attached, but secondary buffer present"; | 230 return "Message has no handles attached, but secondary buffer present"; |
| 233 #endif | 231 #endif |
| 234 | 232 |
| 235 // Sanity-check |num_handles| (before multiplying it against anything). | 233 // Sanity-check |num_handles| (before multiplying it against anything). |
| 236 if (num_handles > kMaxMessageNumHandles) | 234 if (num_handles > GetConfiguration().max_message_num_handles) |
| 237 return "Message handle payload too large"; | 235 return "Message handle payload too large"; |
| 238 | 236 |
| 239 if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) | 237 if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) |
| 240 return "Message secondary buffer too small"; | 238 return "Message secondary buffer too small"; |
| 241 | 239 |
| 242 if (header->num_platform_handles == 0) { | 240 if (header->num_platform_handles == 0) { |
| 243 // Then |platform_handle_table_offset| should also be zero. | 241 // Then |platform_handle_table_offset| should also be zero. |
| 244 if (header->platform_handle_table_offset != 0) { | 242 if (header->platform_handle_table_offset != 0) { |
| 245 return "Message has no handles attached, but platform handle table " | 243 return "Message has no handles attached, but platform handle table " |
| 246 "present"; | 244 "present"; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 const void* source = static_cast<const char*>(buffer) + offset; | 335 const void* source = static_cast<const char*>(buffer) + offset; |
| 338 (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( | 336 (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( |
| 339 channel, handle_table[i].type, source, size, platform_handles.get()); | 337 channel, handle_table[i].type, source, size, platform_handles.get()); |
| 340 } | 338 } |
| 341 | 339 |
| 342 return dispatchers.Pass(); | 340 return dispatchers.Pass(); |
| 343 } | 341 } |
| 344 | 342 |
| 345 } // namespace system | 343 } // namespace system |
| 346 } // namespace mojo | 344 } // namespace mojo |
| OLD | NEW |