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 |