| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/public/cpp/bindings/lib/validation_util.h" | 5 #include "mojo/public/cpp/bindings/lib/validation_util.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 | 10 |
| 11 #include "mojo/public/cpp/bindings/lib/message_internal.h" | 11 #include "mojo/public/cpp/bindings/lib/message_internal.h" |
| 12 #include "mojo/public/cpp/bindings/lib/serialization_util.h" | 12 #include "mojo/public/cpp/bindings/lib/serialization_util.h" |
| 13 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 13 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
| 14 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" | 14 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" |
| 15 | 15 |
| 16 namespace mojo { | 16 namespace mojo { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 bool ValidateEncodedPointer(const uint64_t* offset) { | 19 bool ValidateEncodedPointer(const uint64_t* offset) { |
| 20 // - Make sure |*offset| is no more than 32-bits. | 20 // - Make sure |*offset| is no more than 32-bits. |
| 21 // - Cast |offset| to uintptr_t so overflow behavior is well defined across | 21 // - Cast |offset| to uintptr_t so overflow behavior is well defined across |
| 22 // 32-bit and 64-bit systems. | 22 // 32-bit and 64-bit systems. |
| 23 return *offset <= std::numeric_limits<uint32_t>::max() && | 23 return *offset <= std::numeric_limits<uint32_t>::max() && |
| 24 (reinterpret_cast<uintptr_t>(offset) + | 24 (reinterpret_cast<uintptr_t>(offset) + |
| 25 static_cast<uint32_t>(*offset) >= | 25 static_cast<uint32_t>(*offset) >= |
| 26 reinterpret_cast<uintptr_t>(offset)); | 26 reinterpret_cast<uintptr_t>(offset)); |
| 27 } | 27 } |
| 28 | 28 |
| 29 bool ValidateStructHeaderAndClaimMemory(const void* data, | 29 bool ValidateStructHeaderAndClaimMemory(const void* data, |
| 30 BoundsChecker* bounds_checker) { | 30 ValidationContext* validation_context) { |
| 31 if (!IsAligned(data)) { | 31 if (!IsAligned(data)) { |
| 32 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); | 32 ReportValidationError(validation_context, |
| 33 VALIDATION_ERROR_MISALIGNED_OBJECT); |
| 33 return false; | 34 return false; |
| 34 } | 35 } |
| 35 if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) { | 36 if (!validation_context->IsValidRange(data, sizeof(StructHeader))) { |
| 36 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 37 ReportValidationError(validation_context, |
| 38 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
| 37 return false; | 39 return false; |
| 38 } | 40 } |
| 39 | 41 |
| 40 const StructHeader* header = static_cast<const StructHeader*>(data); | 42 const StructHeader* header = static_cast<const StructHeader*>(data); |
| 41 | 43 |
| 42 if (header->num_bytes < sizeof(StructHeader)) { | 44 if (header->num_bytes < sizeof(StructHeader)) { |
| 43 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); | 45 ReportValidationError(validation_context, |
| 46 VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
| 44 return false; | 47 return false; |
| 45 } | 48 } |
| 46 | 49 |
| 47 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { | 50 if (!validation_context->ClaimMemory(data, header->num_bytes)) { |
| 48 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 51 ReportValidationError(validation_context, |
| 52 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
| 49 return false; | 53 return false; |
| 50 } | 54 } |
| 51 | 55 |
| 52 return true; | 56 return true; |
| 53 } | 57 } |
| 54 | 58 |
| 55 bool ValidateUnionHeaderAndClaimMemory(const void* data, | 59 bool ValidateUnionHeaderAndClaimMemory(const void* data, |
| 56 bool inlined, | 60 bool inlined, |
| 57 BoundsChecker* bounds_checker) { | 61 ValidationContext* validation_context) { |
| 58 if (!IsAligned(data)) { | 62 if (!IsAligned(data)) { |
| 59 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); | 63 ReportValidationError(validation_context, |
| 64 VALIDATION_ERROR_MISALIGNED_OBJECT); |
| 60 return false; | 65 return false; |
| 61 } | 66 } |
| 62 | 67 |
| 63 // If the union is inlined in another structure its memory was already | 68 // If the union is inlined in another structure its memory was already |
| 64 // claimed. | 69 // claimed. |
| 65 // This ONLY applies to the union itself, NOT anything which the union points | 70 // This ONLY applies to the union itself, NOT anything which the union points |
| 66 // to. | 71 // to. |
| 67 if (!inlined && !bounds_checker->ClaimMemory(data, kUnionDataSize)) { | 72 if (!inlined && !validation_context->ClaimMemory(data, kUnionDataSize)) { |
| 68 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 73 ReportValidationError(validation_context, |
| 74 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
| 69 return false; | 75 return false; |
| 70 } | 76 } |
| 71 | 77 |
| 72 return true; | 78 return true; |
| 73 } | 79 } |
| 74 | 80 |
| 75 bool ValidateMessageIsRequestWithoutResponse(const Message* message) { | 81 bool ValidateMessageIsRequestWithoutResponse( |
| 82 const Message* message, |
| 83 ValidationContext* validation_context) { |
| 76 if (message->has_flag(kMessageIsResponse) || | 84 if (message->has_flag(kMessageIsResponse) || |
| 77 message->has_flag(kMessageExpectsResponse)) { | 85 message->has_flag(kMessageExpectsResponse)) { |
| 78 ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); | 86 ReportValidationError(validation_context, |
| 87 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); |
| 79 return false; | 88 return false; |
| 80 } | 89 } |
| 81 return true; | 90 return true; |
| 82 } | 91 } |
| 83 | 92 |
| 84 bool ValidateMessageIsRequestExpectingResponse(const Message* message) { | 93 bool ValidateMessageIsRequestExpectingResponse( |
| 94 const Message* message, |
| 95 ValidationContext* validation_context) { |
| 85 if (message->has_flag(kMessageIsResponse) || | 96 if (message->has_flag(kMessageIsResponse) || |
| 86 !message->has_flag(kMessageExpectsResponse)) { | 97 !message->has_flag(kMessageExpectsResponse)) { |
| 87 ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); | 98 ReportValidationError(validation_context, |
| 99 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); |
| 88 return false; | 100 return false; |
| 89 } | 101 } |
| 90 return true; | 102 return true; |
| 91 } | 103 } |
| 92 | 104 |
| 93 bool ValidateMessageIsResponse(const Message* message) { | 105 bool ValidateMessageIsResponse(const Message* message, |
| 106 ValidationContext* validation_context) { |
| 94 if (message->has_flag(kMessageExpectsResponse) || | 107 if (message->has_flag(kMessageExpectsResponse) || |
| 95 !message->has_flag(kMessageIsResponse)) { | 108 !message->has_flag(kMessageIsResponse)) { |
| 96 ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); | 109 ReportValidationError(validation_context, |
| 110 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); |
| 97 return false; | 111 return false; |
| 98 } | 112 } |
| 99 return true; | 113 return true; |
| 100 } | 114 } |
| 101 | 115 |
| 102 bool ValidateControlRequest(const Message* message) { | 116 bool ValidateControlRequest(const Message* message, |
| 117 ValidationContext* validation_context) { |
| 103 switch (message->header()->name) { | 118 switch (message->header()->name) { |
| 104 case kRunMessageId: | 119 case kRunMessageId: |
| 105 return ValidateMessageIsRequestExpectingResponse(message) && | 120 return ValidateMessageIsRequestExpectingResponse(message, |
| 106 ValidateMessagePayload<RunMessageParams_Data>(message); | 121 validation_context) && |
| 122 ValidateMessagePayload<RunMessageParams_Data>(message, |
| 123 validation_context); |
| 107 case kRunOrClosePipeMessageId: | 124 case kRunOrClosePipeMessageId: |
| 108 return ValidateMessageIsRequestWithoutResponse(message) && | 125 return ValidateMessageIsRequestWithoutResponse(message, |
| 109 ValidateMessagePayload<RunOrClosePipeMessageParams_Data>(message); | 126 validation_context) && |
| 127 ValidateMessagePayload<RunOrClosePipeMessageParams_Data>( |
| 128 message, validation_context); |
| 110 } | 129 } |
| 111 return false; | 130 return false; |
| 112 } | 131 } |
| 113 | 132 |
| 114 bool ValidateControlResponse(const Message* message) { | 133 bool ValidateControlResponse(const Message* message, |
| 115 if (!ValidateMessageIsResponse(message)) | 134 ValidationContext* validation_context) { |
| 135 if (!ValidateMessageIsResponse(message, validation_context)) |
| 116 return false; | 136 return false; |
| 117 switch (message->header()->name) { | 137 switch (message->header()->name) { |
| 118 case kRunMessageId: | 138 case kRunMessageId: |
| 119 return ValidateMessagePayload<RunResponseMessageParams_Data>(message); | 139 return ValidateMessagePayload<RunResponseMessageParams_Data>( |
| 140 message, validation_context); |
| 120 } | 141 } |
| 121 return false; | 142 return false; |
| 122 } | 143 } |
| 123 | 144 |
| 124 bool ValidateHandleNonNullable(const Handle_Data& input, | 145 bool ValidateHandleNonNullable(const Handle_Data& input, |
| 125 const char* error_message) { | 146 const char* error_message, |
| 147 ValidationContext* validation_context) { |
| 126 if (input.is_valid()) | 148 if (input.is_valid()) |
| 127 return true; | 149 return true; |
| 128 | 150 |
| 129 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | 151 ReportValidationError(validation_context, |
| 152 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, |
| 130 error_message); | 153 error_message); |
| 131 return false; | 154 return false; |
| 132 } | 155 } |
| 133 | 156 |
| 134 bool ValidateInterfaceIdNonNullable(InterfaceId input, | 157 bool ValidateInterfaceIdNonNullable(InterfaceId input, |
| 135 const char* error_message) { | 158 const char* error_message, |
| 159 ValidationContext* validation_context) { |
| 136 if (IsValidInterfaceId(input)) | 160 if (IsValidInterfaceId(input)) |
| 137 return true; | 161 return true; |
| 138 | 162 |
| 139 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, | 163 ReportValidationError(validation_context, |
| 164 VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, |
| 140 error_message); | 165 error_message); |
| 141 return false; | 166 return false; |
| 142 } | 167 } |
| 143 | 168 |
| 144 bool ValidateHandle(const Handle_Data& input, BoundsChecker* bounds_checker) { | 169 bool ValidateHandle(const Handle_Data& input, |
| 145 if (bounds_checker->ClaimHandle(input)) | 170 ValidationContext* validation_context) { |
| 171 if (validation_context->ClaimHandle(input)) |
| 146 return true; | 172 return true; |
| 147 | 173 |
| 148 ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE); | 174 ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE); |
| 149 return false; | 175 return false; |
| 150 } | 176 } |
| 151 | 177 |
| 152 bool ValidateAssociatedInterfaceId(InterfaceId input) { | 178 bool ValidateAssociatedInterfaceId(InterfaceId input, |
| 179 ValidationContext* validation_context) { |
| 153 if (!IsMasterInterfaceId(input)) | 180 if (!IsMasterInterfaceId(input)) |
| 154 return true; | 181 return true; |
| 155 | 182 |
| 156 ReportValidationError(VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); | 183 ReportValidationError(validation_context, |
| 184 VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); |
| 157 return false; | 185 return false; |
| 158 } | 186 } |
| 159 | 187 |
| 160 } // namespace internal | 188 } // namespace internal |
| 161 } // namespace mojo | 189 } // namespace mojo |
| OLD | NEW |