| 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/system/transport_data.h" | 5 #include "mojo/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" |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 } | 194 } |
| 195 | 195 |
| 196 TransportData::~TransportData() { | 196 TransportData::~TransportData() { |
| 197 if (platform_handles_) { | 197 if (platform_handles_) { |
| 198 for (size_t i = 0; i < platform_handles_->size(); i++) | 198 for (size_t i = 0; i < platform_handles_->size(); i++) |
| 199 (*platform_handles_)[i].CloseIfNecessary(); | 199 (*platform_handles_)[i].CloseIfNecessary(); |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 | 202 |
| 203 // static | 203 // static |
| 204 const char* TransportData::ValidateBuffer(const void* buffer, | 204 const char* TransportData::ValidateBuffer( |
| 205 size_t buffer_size) { | 205 size_t serialized_platform_handle_size, |
| 206 const void* buffer, |
| 207 size_t buffer_size) { |
| 206 DCHECK(buffer); | 208 DCHECK(buffer); |
| 207 DCHECK_GT(buffer_size, 0u); | 209 DCHECK_GT(buffer_size, 0u); |
| 208 | 210 |
| 209 // Always make sure that the buffer size is sane; if it's not, someone's | 211 // Always make sure that the buffer size is sane; if it's not, someone's |
| 210 // messing with us. | 212 // messing with us. |
| 211 if (buffer_size < sizeof(Header) || buffer_size > kMaxBufferSize || | 213 if (buffer_size < sizeof(Header) || buffer_size > kMaxBufferSize || |
| 212 buffer_size % MessageInTransit::kMessageAlignment != 0) | 214 buffer_size % MessageInTransit::kMessageAlignment != 0) |
| 213 return "Invalid message secondary buffer size"; | 215 return "Invalid message secondary buffer size"; |
| 214 | 216 |
| 215 const Header* header = static_cast<const Header*>(buffer); | 217 const Header* header = static_cast<const Header*>(buffer); |
| 216 const size_t num_handles = header->num_handles; | 218 const size_t num_handles = header->num_handles; |
| 217 if (num_handles == 0) | 219 if (num_handles == 0) |
| 218 return "Message has no handles attached, but secondary buffer present"; | 220 return "Message has no handles attached, but secondary buffer present"; |
| 219 | 221 |
| 220 // Sanity-check |num_handles| (before multiplying it against anything). | 222 // Sanity-check |num_handles| (before multiplying it against anything). |
| 221 if (num_handles > kMaxMessageNumHandles) | 223 if (num_handles > kMaxMessageNumHandles) |
| 222 return "Message handle payload too large"; | 224 return "Message handle payload too large"; |
| 223 | 225 |
| 224 if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) | 226 if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) |
| 225 return "Message secondary buffer too small"; | 227 return "Message secondary buffer too small"; |
| 226 | 228 |
| 227 // TODO(vtl): Check |platform_handle_table_offset| and |num_platform_handles| | 229 if (header->num_platform_handles == 0) { |
| 228 // once they're used. | 230 // Then |platform_handle_table_offset| should also be zero. |
| 229 if (header->platform_handle_table_offset != 0 || | 231 if (header->platform_handle_table_offset != 0) { |
| 230 header->num_platform_handles != 0) | 232 return |
| 231 return "Bad message secondary buffer header values"; | 233 "Message has no handles attached, but platform handle table present"; |
| 234 } |
| 235 } else { |
| 236 // |num_handles| has already been validated, so the multiplication is okay. |
| 237 if (header->num_platform_handles > |
| 238 num_handles * kMaxSerializedDispatcherPlatformHandles) |
| 239 return "Message has too many platform handles attached"; |
| 240 |
| 241 static const char kInvalidPlatformHandleTableOffset[] = |
| 242 "Message has invalid platform handle table offset"; |
| 243 // This doesn't check that the platform handle table doesn't alias other |
| 244 // stuff, but it doesn't matter, since it's all read-only. |
| 245 if (header->platform_handle_table_offset % |
| 246 MessageInTransit::kMessageAlignment != 0) |
| 247 return kInvalidPlatformHandleTableOffset; |
| 248 |
| 249 // ">" instead of ">=" since the size per handle may be zero. |
| 250 if (header->platform_handle_table_offset > buffer_size) |
| 251 return kInvalidPlatformHandleTableOffset; |
| 252 |
| 253 // We already checked |platform_handle_table_offset| and |
| 254 // |num_platform_handles|, so the addition and multiplication are okay. |
| 255 if (header->platform_handle_table_offset + |
| 256 header->num_platform_handles * serialized_platform_handle_size > |
| 257 buffer_size) |
| 258 return kInvalidPlatformHandleTableOffset; |
| 259 } |
| 232 | 260 |
| 233 const HandleTableEntry* handle_table = | 261 const HandleTableEntry* handle_table = |
| 234 reinterpret_cast<const HandleTableEntry*>( | 262 reinterpret_cast<const HandleTableEntry*>( |
| 235 static_cast<const char*>(buffer) + sizeof(Header)); | 263 static_cast<const char*>(buffer) + sizeof(Header)); |
| 236 static const char kInvalidSerializedDispatcher[] = | 264 static const char kInvalidSerializedDispatcher[] = |
| 237 "Message contains invalid serialized dispatcher"; | 265 "Message contains invalid serialized dispatcher"; |
| 238 for (size_t i = 0; i < num_handles; i++) { | 266 for (size_t i = 0; i < num_handles; i++) { |
| 239 size_t offset = handle_table[i].offset; | 267 size_t offset = handle_table[i].offset; |
| 240 if (offset % MessageInTransit::kMessageAlignment != 0) | 268 if (offset % MessageInTransit::kMessageAlignment != 0) |
| 241 return kInvalidSerializedDispatcher; | 269 return kInvalidSerializedDispatcher; |
| 242 | 270 |
| 243 size_t size = handle_table[i].size; | 271 size_t size = handle_table[i].size; |
| 244 if (size > kMaxSerializedDispatcherSize || size > buffer_size) | 272 if (size > kMaxSerializedDispatcherSize || size > buffer_size) |
| 245 return kInvalidSerializedDispatcher; | 273 return kInvalidSerializedDispatcher; |
| 246 | 274 |
| 247 // Note: This is an overflow-safe check for |offset + size > buffer_size| | 275 // Note: This is an overflow-safe check for |offset + size > buffer_size| |
| 248 // (we know that |size <= buffer_size| from the previous check). | 276 // (we know that |size <= buffer_size| from the previous check). |
| 249 if (offset > buffer_size - size) | 277 if (offset > buffer_size - size) |
| 250 return kInvalidSerializedDispatcher; | 278 return kInvalidSerializedDispatcher; |
| 251 } | 279 } |
| 252 | 280 |
| 253 return NULL; | 281 return NULL; |
| 254 } | 282 } |
| 255 | 283 |
| 256 // static | 284 // static |
| 285 void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, |
| 286 size_t* num_platform_handles, |
| 287 const void** platform_handle_table) { |
| 288 DCHECK(transport_data_buffer); |
| 289 DCHECK(num_platform_handles); |
| 290 DCHECK(platform_handle_table); |
| 291 |
| 292 const Header* header = static_cast<const Header*>(transport_data_buffer); |
| 293 *num_platform_handles = header->num_platform_handles; |
| 294 *platform_handle_table = static_cast<const char*>(transport_data_buffer) + |
| 295 header->platform_handle_table_offset; |
| 296 } |
| 297 |
| 298 // static |
| 257 scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchersFromBuffer( | 299 scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchersFromBuffer( |
| 258 const void* buffer, | 300 const void* buffer, |
| 259 size_t buffer_size, | 301 size_t buffer_size, |
| 260 Channel* channel) { | 302 Channel* channel) { |
| 261 DCHECK(buffer); | 303 DCHECK(buffer); |
| 262 DCHECK_GT(buffer_size, 0u); | 304 DCHECK_GT(buffer_size, 0u); |
| 263 DCHECK(channel); | 305 DCHECK(channel); |
| 264 | 306 |
| 265 const Header* header = static_cast<const Header*>(buffer); | 307 const Header* header = static_cast<const Header*>(buffer); |
| 266 const size_t num_handles = header->num_handles; | 308 const size_t num_handles = header->num_handles; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 280 const void* source = static_cast<const char*>(buffer) + offset; | 322 const void* source = static_cast<const char*>(buffer) + offset; |
| 281 (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( | 323 (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( |
| 282 channel, handle_table[i].type, source, size); | 324 channel, handle_table[i].type, source, size); |
| 283 } | 325 } |
| 284 | 326 |
| 285 return dispatchers.Pass(); | 327 return dispatchers.Pass(); |
| 286 } | 328 } |
| 287 | 329 |
| 288 } // namespace system | 330 } // namespace system |
| 289 } // namespace mojo | 331 } // namespace mojo |
| OLD | NEW |