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