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 |