• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "mojo/public/cpp/bindings/lib/validation_util.h"
6 
7 #include <stdint.h>
8 
9 #include <limits>
10 
11 #include "mojo/public/cpp/bindings/lib/message_internal.h"
12 #include "mojo/public/cpp/bindings/lib/serialization_util.h"
13 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
14 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
15 
16 namespace mojo {
17 namespace internal {
18 
ValidateEncodedPointer(const uint64_t * offset)19 bool ValidateEncodedPointer(const uint64_t* offset) {
20   // - Make sure |*offset| is no more than 32-bits.
21   // - Cast |offset| to uintptr_t so overflow behavior is well defined across
22   //   32-bit and 64-bit systems.
23   return *offset <= std::numeric_limits<uint32_t>::max() &&
24          (reinterpret_cast<uintptr_t>(offset) +
25               static_cast<uint32_t>(*offset) >=
26           reinterpret_cast<uintptr_t>(offset));
27 }
28 
ValidateStructHeaderAndClaimMemory(const void * data,ValidationContext * validation_context)29 bool ValidateStructHeaderAndClaimMemory(const void* data,
30                                         ValidationContext* validation_context) {
31   if (!IsAligned(data)) {
32     ReportValidationError(validation_context,
33                           VALIDATION_ERROR_MISALIGNED_OBJECT);
34     return false;
35   }
36   if (!validation_context->IsValidRange(data, sizeof(StructHeader))) {
37     ReportValidationError(validation_context,
38                           VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
39     return false;
40   }
41 
42   const StructHeader* header = static_cast<const StructHeader*>(data);
43 
44   if (header->num_bytes < sizeof(StructHeader)) {
45     ReportValidationError(validation_context,
46                           VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
47     return false;
48   }
49 
50   if (!validation_context->ClaimMemory(data, header->num_bytes)) {
51     ReportValidationError(validation_context,
52                           VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
53     return false;
54   }
55 
56   return true;
57 }
58 
ValidateUnionHeaderAndClaimMemory(const void * data,bool inlined,ValidationContext * validation_context)59 bool ValidateUnionHeaderAndClaimMemory(const void* data,
60                                        bool inlined,
61                                        ValidationContext* validation_context) {
62   if (!IsAligned(data)) {
63     ReportValidationError(validation_context,
64                           VALIDATION_ERROR_MISALIGNED_OBJECT);
65     return false;
66   }
67 
68   // If the union is inlined in another structure its memory was already
69   // claimed.
70   // This ONLY applies to the union itself, NOT anything which the union points
71   // to.
72   if (!inlined && !validation_context->ClaimMemory(data, kUnionDataSize)) {
73     ReportValidationError(validation_context,
74                           VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
75     return false;
76   }
77 
78   return true;
79 }
80 
ValidateMessageIsRequestWithoutResponse(const Message * message,ValidationContext * validation_context)81 bool ValidateMessageIsRequestWithoutResponse(
82     const Message* message,
83     ValidationContext* validation_context) {
84   if (message->has_flag(Message::kFlagIsResponse) ||
85       message->has_flag(Message::kFlagExpectsResponse)) {
86     ReportValidationError(validation_context,
87                           VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS);
88     return false;
89   }
90   return true;
91 }
92 
ValidateMessageIsRequestExpectingResponse(const Message * message,ValidationContext * validation_context)93 bool ValidateMessageIsRequestExpectingResponse(
94     const Message* message,
95     ValidationContext* validation_context) {
96   if (message->has_flag(Message::kFlagIsResponse) ||
97       !message->has_flag(Message::kFlagExpectsResponse)) {
98     ReportValidationError(validation_context,
99                           VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS);
100     return false;
101   }
102   return true;
103 }
104 
ValidateMessageIsResponse(const Message * message,ValidationContext * validation_context)105 bool ValidateMessageIsResponse(const Message* message,
106                                ValidationContext* validation_context) {
107   if (message->has_flag(Message::kFlagExpectsResponse) ||
108       !message->has_flag(Message::kFlagIsResponse)) {
109     ReportValidationError(validation_context,
110                           VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS);
111     return false;
112   }
113   return true;
114 }
115 
ValidateControlRequest(const Message * message,ValidationContext * validation_context)116 bool ValidateControlRequest(const Message* message,
117                             ValidationContext* validation_context) {
118   switch (message->header()->name) {
119     case kRunMessageId:
120       return ValidateMessageIsRequestExpectingResponse(message,
121                                                        validation_context) &&
122              ValidateMessagePayload<RunMessageParams_Data>(message,
123                                                            validation_context);
124     case kRunOrClosePipeMessageId:
125       return ValidateMessageIsRequestWithoutResponse(message,
126                                                      validation_context) &&
127           ValidateMessagePayload<RunOrClosePipeMessageParams_Data>(
128               message, validation_context);
129   }
130   return false;
131 }
132 
ValidateControlResponse(const Message * message,ValidationContext * validation_context)133 bool ValidateControlResponse(const Message* message,
134                              ValidationContext* validation_context) {
135   if (!ValidateMessageIsResponse(message, validation_context))
136     return false;
137   switch (message->header()->name) {
138     case kRunMessageId:
139       return ValidateMessagePayload<RunResponseMessageParams_Data>(
140           message, validation_context);
141   }
142   return false;
143 }
144 
IsHandleOrInterfaceValid(const AssociatedInterface_Data & input)145 bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input) {
146   return IsValidInterfaceId(input.interface_id);
147 }
148 
IsHandleOrInterfaceValid(const AssociatedInterfaceRequest_Data & input)149 bool IsHandleOrInterfaceValid(const AssociatedInterfaceRequest_Data& input) {
150   return IsValidInterfaceId(input.interface_id);
151 }
152 
IsHandleOrInterfaceValid(const Interface_Data & input)153 bool IsHandleOrInterfaceValid(const Interface_Data& input) {
154   return input.handle.is_valid();
155 }
156 
IsHandleOrInterfaceValid(const Handle_Data & input)157 bool IsHandleOrInterfaceValid(const Handle_Data& input) {
158   return input.is_valid();
159 }
160 
ValidateHandleOrInterfaceNonNullable(const AssociatedInterface_Data & input,const char * error_message,ValidationContext * validation_context)161 bool ValidateHandleOrInterfaceNonNullable(
162     const AssociatedInterface_Data& input,
163     const char* error_message,
164     ValidationContext* validation_context) {
165   if (IsHandleOrInterfaceValid(input))
166     return true;
167 
168   ReportValidationError(validation_context,
169                         VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
170                         error_message);
171   return false;
172 }
173 
ValidateHandleOrInterfaceNonNullable(const AssociatedInterfaceRequest_Data & input,const char * error_message,ValidationContext * validation_context)174 bool ValidateHandleOrInterfaceNonNullable(
175     const AssociatedInterfaceRequest_Data& input,
176     const char* error_message,
177     ValidationContext* validation_context) {
178   if (IsHandleOrInterfaceValid(input))
179     return true;
180 
181   ReportValidationError(validation_context,
182                         VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
183                         error_message);
184   return false;
185 }
186 
ValidateHandleOrInterfaceNonNullable(const Interface_Data & input,const char * error_message,ValidationContext * validation_context)187 bool ValidateHandleOrInterfaceNonNullable(
188     const Interface_Data& input,
189     const char* error_message,
190     ValidationContext* validation_context) {
191   if (IsHandleOrInterfaceValid(input))
192     return true;
193 
194   ReportValidationError(validation_context,
195                         VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
196                         error_message);
197   return false;
198 }
199 
ValidateHandleOrInterfaceNonNullable(const Handle_Data & input,const char * error_message,ValidationContext * validation_context)200 bool ValidateHandleOrInterfaceNonNullable(
201     const Handle_Data& input,
202     const char* error_message,
203     ValidationContext* validation_context) {
204   if (IsHandleOrInterfaceValid(input))
205     return true;
206 
207   ReportValidationError(validation_context,
208                         VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
209                         error_message);
210   return false;
211 }
212 
ValidateHandleOrInterface(const AssociatedInterface_Data & input,ValidationContext * validation_context)213 bool ValidateHandleOrInterface(const AssociatedInterface_Data& input,
214                                ValidationContext* validation_context) {
215   if (!IsMasterInterfaceId(input.interface_id))
216     return true;
217 
218   ReportValidationError(validation_context,
219                         VALIDATION_ERROR_ILLEGAL_INTERFACE_ID);
220   return false;
221 }
222 
ValidateHandleOrInterface(const AssociatedInterfaceRequest_Data & input,ValidationContext * validation_context)223 bool ValidateHandleOrInterface(const AssociatedInterfaceRequest_Data& input,
224                                ValidationContext* validation_context) {
225   if (!IsMasterInterfaceId(input.interface_id))
226     return true;
227 
228   ReportValidationError(validation_context,
229                         VALIDATION_ERROR_ILLEGAL_INTERFACE_ID);
230   return false;
231 }
232 
ValidateHandleOrInterface(const Interface_Data & input,ValidationContext * validation_context)233 bool ValidateHandleOrInterface(const Interface_Data& input,
234                                ValidationContext* validation_context) {
235   if (validation_context->ClaimHandle(input.handle))
236     return true;
237 
238   ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE);
239   return false;
240 }
241 
ValidateHandleOrInterface(const Handle_Data & input,ValidationContext * validation_context)242 bool ValidateHandleOrInterface(const Handle_Data& input,
243                                ValidationContext* validation_context) {
244   if (validation_context->ClaimHandle(input))
245     return true;
246 
247   ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE);
248   return false;
249 }
250 
251 }  // namespace internal
252 }  // namespace mojo
253