Home | History | Annotate | Download | only in lib
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    145 bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input) {
    146   return IsValidInterfaceId(input.interface_id);
    147 }
    148 
    149 bool IsHandleOrInterfaceValid(const AssociatedInterfaceRequest_Data& input) {
    150   return IsValidInterfaceId(input.interface_id);
    151 }
    152 
    153 bool IsHandleOrInterfaceValid(const Interface_Data& input) {
    154   return input.handle.is_valid();
    155 }
    156 
    157 bool IsHandleOrInterfaceValid(const Handle_Data& input) {
    158   return input.is_valid();
    159 }
    160 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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