Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: mojo/system/message_in_transit.cc

Issue 227703012: Mojo: MessageInTransit clean-up. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/message_in_transit.h" 5 #include "mojo/system/message_in_transit.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <new> 9 #include <new>
10 10
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/aligned_memory.h" 13 #include "base/memory/aligned_memory.h"
14 #include "mojo/system/constants.h" 14 #include "mojo/system/constants.h"
15 15
16 namespace mojo { 16 namespace mojo {
17 namespace system { 17 namespace system {
18 18
19 namespace {
20
21
22 } // namespace
23
24 struct MessageInTransit::PrivateStructForCompileAsserts { 19 struct MessageInTransit::PrivateStructForCompileAsserts {
25 // The size of |Header| must be appropriate to maintain alignment of the 20 // The size of |Header| must be a multiple of the alignment.
26 // following data.
27 COMPILE_ASSERT(sizeof(Header) % kMessageAlignment == 0, 21 COMPILE_ASSERT(sizeof(Header) % kMessageAlignment == 0,
28 sizeof_MessageInTransit_Header_invalid); 22 sizeof_MessageInTransit_Header_invalid);
29 // Avoid dangerous situations, but making sure that the size of the "header" + 23 // Avoid dangerous situations, but making sure that the size of the "header" +
30 // the size of the data fits into a 31-bit number. 24 // the size of the data fits into a 31-bit number.
31 COMPILE_ASSERT(static_cast<uint64_t>(sizeof(Header)) + kMaxMessageNumBytes <= 25 COMPILE_ASSERT(static_cast<uint64_t>(sizeof(Header)) + kMaxMessageNumBytes <=
32 0x7fffffffULL, 26 0x7fffffffULL,
33 kMaxMessageNumBytes_too_big); 27 kMaxMessageNumBytes_too_big);
34 28
35 // We assume (to avoid extra rounding code) that the maximum message (data) 29 // We assume (to avoid extra rounding code) that the maximum message (data)
36 // size is a multiple of the alignment. 30 // size is a multiple of the alignment.
37 COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0, 31 COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0,
38 kMessageAlignment_not_a_multiple_of_alignment); 32 kMessageAlignment_not_a_multiple_of_alignment);
39 33
34 // The maximum serialized dispatcher size must be a multiple of the alignment.
40 COMPILE_ASSERT(kMaxSerializedDispatcherSize % kMessageAlignment == 0, 35 COMPILE_ASSERT(kMaxSerializedDispatcherSize % kMessageAlignment == 0,
41 kMaxSerializedDispatcherSize_not_a_multiple_of_alignment); 36 kMaxSerializedDispatcherSize_not_a_multiple_of_alignment);
42 37
43 // The size of |HandleTableEntry| must be appropriate to maintain alignment. 38 // The size of |HandleTableEntry| must be a multiple of the alignment.
44 COMPILE_ASSERT(sizeof(HandleTableEntry) % kMessageAlignment == 0, 39 COMPILE_ASSERT(sizeof(HandleTableEntry) % kMessageAlignment == 0,
45 sizeof_MessageInTransit_HandleTableEntry_invalid); 40 sizeof_MessageInTransit_HandleTableEntry_invalid);
46 }; 41 };
47 42
48 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 43 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
49 MessageInTransit::kTypeMessagePipeEndpoint; 44 MessageInTransit::kTypeMessagePipeEndpoint;
50 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 45 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
51 MessageInTransit::kTypeMessagePipe; 46 MessageInTransit::kTypeMessagePipe;
52 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 47 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
53 MessageInTransit::kTypeChannel; 48 MessageInTransit::kTypeChannel;
54 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 49 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
55 MessageInTransit::kSubtypeMessagePipeEndpointData; 50 MessageInTransit::kSubtypeMessagePipeEndpointData;
56 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 51 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
57 MessageInTransit::kSubtypeMessagePipePeerClosed; 52 MessageInTransit::kSubtypeMessagePipePeerClosed;
58 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId 53 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
59 MessageInTransit::kInvalidEndpointId; 54 MessageInTransit::kInvalidEndpointId;
60 STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment; 55 STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
61 STATIC_CONST_MEMBER_DEFINITION const size_t 56 STATIC_CONST_MEMBER_DEFINITION const size_t
62 MessageInTransit::kMaxSerializedDispatcherSize; 57 MessageInTransit::kMaxSerializedDispatcherSize;
63 58
59 // For each attached (Mojo) handle, there'll be a handle table entry and
60 // serialized dispatcher data.
64 // static 61 // static
65 const size_t MessageInTransit::kMaxSecondaryBufferSize = kMaxMessageNumHandles * 62 const size_t MessageInTransit::kMaxSecondaryBufferSize = kMaxMessageNumHandles *
66 (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize); 63 (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize);
67 64
68 MessageInTransit::View::View(size_t message_size, const void* buffer) 65 MessageInTransit::View::View(size_t message_size, const void* buffer)
69 : buffer_(buffer) { 66 : buffer_(buffer) {
70 size_t next_message_size = 0; 67 size_t next_message_size = 0;
71 DCHECK(MessageInTransit::GetNextMessageSize(buffer_, message_size, 68 DCHECK(MessageInTransit::GetNextMessageSize(buffer_, message_size,
72 &next_message_size)); 69 &next_message_size));
73 DCHECK_EQ(message_size, next_message_size); 70 DCHECK_EQ(message_size, next_message_size);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 } 246 }
250 247
251 void* destination = static_cast<char*>(secondary_buffer_) + current_offset; 248 void* destination = static_cast<char*>(secondary_buffer_) + current_offset;
252 size_t actual_size = 0; 249 size_t actual_size = 0;
253 if (Dispatcher::MessageInTransitAccess::SerializeAndClose( 250 if (Dispatcher::MessageInTransitAccess::SerializeAndClose(
254 dispatcher, channel, destination, &actual_size)) { 251 dispatcher, channel, destination, &actual_size)) {
255 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); 252 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
256 handle_table[i].offset = static_cast<uint32_t>(current_offset); 253 handle_table[i].offset = static_cast<uint32_t>(current_offset);
257 handle_table[i].size = static_cast<uint32_t>(actual_size); 254 handle_table[i].size = static_cast<uint32_t>(actual_size);
258 } else { 255 } else {
259 // (Nothing to do on failure, since |secondary_buffer_| was cleared, and 256 // Nothing to do on failure, since |secondary_buffer_| was cleared, and
260 // |kTypeUnknown| is zero.) 257 // |kTypeUnknown| is zero. The handle was simply closed.
261 // The handle will simply be closed.
262 LOG(ERROR) << "Failed to serialize handle to remote message pipe"; 258 LOG(ERROR) << "Failed to serialize handle to remote message pipe";
263 } 259 }
264 260
265 current_offset += RoundUpMessageAlignment(actual_size); 261 current_offset += RoundUpMessageAlignment(actual_size);
266 DCHECK_LE(current_offset, size); 262 DCHECK_LE(current_offset, size);
267 } 263 }
268 264
269 UpdateTotalSize(); 265 UpdateTotalSize();
270 } 266 }
271 267
268 // Note: The message's secondary buffer should have been checked by calling
269 // |View::IsValid()| (on the |View|) first.
272 void MessageInTransit::DeserializeDispatchers(Channel* channel) { 270 void MessageInTransit::DeserializeDispatchers(Channel* channel) {
273 DCHECK(!dispatchers_); 271 DCHECK(!dispatchers_);
274 272
275 // This should have been checked by calling |IsValid()| on the |View| first. 273 // Already checked by |View::IsValid()|:
276 DCHECK_LE(num_handles(), kMaxMessageNumHandles); 274 DCHECK_LE(num_handles(), kMaxMessageNumHandles);
277 275
278 if (!num_handles()) 276 if (!num_handles())
279 return; 277 return;
280 278
281 dispatchers_.reset( 279 dispatchers_.reset(
282 new std::vector<scoped_refptr<Dispatcher> >(num_handles())); 280 new std::vector<scoped_refptr<Dispatcher> >(num_handles()));
283 281
284 size_t handle_table_size = num_handles() * sizeof(HandleTableEntry); 282 size_t handle_table_size = num_handles() * sizeof(HandleTableEntry);
285 if (secondary_buffer_size_ < handle_table_size) { 283 // Already checked by |View::IsValid()|:
286 LOG(ERROR) << "Serialized handle table too small"; 284 DCHECK_LE(handle_table_size, secondary_buffer_size_);
287 return;
288 }
289 285
290 const HandleTableEntry* handle_table = 286 const HandleTableEntry* handle_table =
291 static_cast<const HandleTableEntry*>(secondary_buffer_); 287 static_cast<const HandleTableEntry*>(secondary_buffer_);
292 for (size_t i = 0; i < num_handles(); i++) { 288 for (size_t i = 0; i < num_handles(); i++) {
293 size_t offset = handle_table[i].offset; 289 size_t offset = handle_table[i].offset;
294 size_t size = handle_table[i].size; 290 size_t size = handle_table[i].size;
295 // TODO(vtl): Sanity-check the size. 291 // Already checked by |View::IsValid()|:
296 if (offset % kMessageAlignment != 0 || offset > secondary_buffer_size_ || 292 DCHECK_EQ(offset % kMessageAlignment, 0u);
297 offset + size > secondary_buffer_size_) { 293 DCHECK_LE(offset, secondary_buffer_size_);
298 // TODO(vtl): Maybe should report error (and make it possible to kill the 294 DCHECK_LE(offset + size, secondary_buffer_size_);
299 // connection with extreme prejudice).
300 LOG(ERROR) << "Invalid serialized handle table entry";
301 continue;
302 }
303 295
304 const void* source = static_cast<const char*>(secondary_buffer_) + offset; 296 const void* source = static_cast<const char*>(secondary_buffer_) + offset;
305 (*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize( 297 (*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize(
306 channel, handle_table[i].type, source, size); 298 channel, handle_table[i].type, source, size);
307 } 299 }
308 } 300 }
309 301
310 // Validates the secondary buffer. Returns null on success, or a human-readable 302 // Validates the secondary buffer. Returns null on success, or a human-readable
311 // error message on error. 303 // error message on error.
312 // static 304 // static
313 const char* MessageInTransit::ValidateSecondaryBuffer( 305 const char* MessageInTransit::ValidateSecondaryBuffer(
314 size_t num_handles, 306 size_t num_handles,
315 const void* secondary_buffer, 307 const void* secondary_buffer,
316 size_t secondary_buffer_size) { 308 size_t secondary_buffer_size) {
317 if (!num_handles) 309 // Always make sure that the secondary buffer size is sane (even if we have no
310 // handles); if it's not, someone's messing with us.
311 if (secondary_buffer_size > kMaxSecondaryBufferSize)
312 return "Message secondary buffer too large";
313
314 // Fast-path for the common case (no handles => no secondary buffer).
315 if (num_handles == 0) {
316 // We shouldn't have a secondary buffer in this case.
317 if (secondary_buffer_size > 0)
318 return "Message has no handles attached, but secondary buffer present";
318 return NULL; 319 return NULL;
320 }
319 321
322 // Sanity-check |num_handles| (before multiplying it against anything).
320 if (num_handles > kMaxMessageNumHandles) 323 if (num_handles > kMaxMessageNumHandles)
321 return "Message handle payload too large"; 324 return "Message handle payload too large";
322 325
323 if (secondary_buffer_size > kMaxSecondaryBufferSize)
324 return "Message secondary buffer too large";
325
326 if (secondary_buffer_size < num_handles * sizeof(HandleTableEntry)) 326 if (secondary_buffer_size < num_handles * sizeof(HandleTableEntry))
327 return "Message secondary buffer too small"; 327 return "Message secondary buffer too small";
328 328
329 DCHECK(secondary_buffer); 329 DCHECK(secondary_buffer);
330 const HandleTableEntry* handle_table = 330 const HandleTableEntry* handle_table =
331 static_cast<const HandleTableEntry*>(secondary_buffer); 331 static_cast<const HandleTableEntry*>(secondary_buffer);
332 332
333 static const char kInvalidSerializedDispatcher[] = 333 static const char kInvalidSerializedDispatcher[] =
334 "Message contains invalid serialized dispatcher"; 334 "Message contains invalid serialized dispatcher";
335 for (size_t i = 0; i < num_handles; i++) { 335 for (size_t i = 0; i < num_handles; i++) {
(...skipping 17 matching lines...) Expand all
353 353
354 void MessageInTransit::UpdateTotalSize() { 354 void MessageInTransit::UpdateTotalSize() {
355 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); 355 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
356 DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u); 356 DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u);
357 header()->total_size = 357 header()->total_size =
358 static_cast<uint32_t>(main_buffer_size_ + secondary_buffer_size_); 358 static_cast<uint32_t>(main_buffer_size_ + secondary_buffer_size_);
359 } 359 }
360 360
361 } // namespace system 361 } // namespace system
362 } // namespace mojo 362 } // namespace mojo
OLDNEW
« mojo/system/message_in_transit.h ('K') | « mojo/system/message_in_transit.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698