security/sandbox/win/src/crosscall_params.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2012 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.
     5 #ifndef SANDBOX_SRC_CROSSCALL_PARAMS_H__
     6 #define SANDBOX_SRC_CROSSCALL_PARAMS_H__
     8 #include <windows.h>
     9 #include <lmaccess.h>
    11 #include <memory>
    13 #include "base/basictypes.h"
    14 #include "sandbox/win/src/internal_types.h"
    15 #include "sandbox/win/src/sandbox_types.h"
    17 namespace {
    19 // Increases |value| until there is no need for padding given an int64
    20 // alignment. Returns the increased value.
    21 uint32 Align(uint32 value) {
    22   uint32 alignment = sizeof(int64);
    23   return ((value + alignment - 1) / alignment) * alignment;
    24 }
    26 }
    27 // This header is part of CrossCall: the sandbox inter-process communication.
    28 // This header defines the basic types used both in the client IPC and in the
    29 // server IPC code. CrossCallParams and ActualCallParams model the input
    30 // parameters of an IPC call and CrossCallReturn models the output params and
    31 // the return value.
    32 //
    33 // An IPC call is defined by its 'tag' which is a (uint32) unique identifier
    34 // that is used to route the IPC call to the proper server. Every tag implies
    35 // a complete call signature including the order and type of each parameter.
    36 //
    37 // Like most IPC systems. CrossCall is designed to take as inputs 'simple'
    38 // types such as integers and strings. Classes, generic arrays or pointers to
    39 // them are not supported.
    40 //
    41 // Another limitation of CrossCall is that the return value and output
    42 // parameters can only be uint32 integers. Returning complex structures or
    43 // strings is not supported.
    45 namespace sandbox {
    47 // max number of extended return parameters. See CrossCallReturn
    48 const size_t kExtendedReturnCount = 8;
    50 // Union of multiple types to be used as extended results
    51 // in the CrossCallReturn.
    52 union MultiType {
    53   uint32 unsigned_int;
    54   void* pointer;
    55   HANDLE handle;
    56   ULONG_PTR ulong_ptr;
    57 };
    59 // Maximum number of IPC parameters currently supported.
    60 // To increase this value, we have to:
    61 //  - Add another Callback typedef to Dispatcher.
    62 //  - Add another case to the switch on SharedMemIPCServer::InvokeCallback.
    63 //  - Add another case to the switch in GetActualAndMaxBufferSize
    64 const int kMaxIpcParams = 9;
    66 // Contains the information about a parameter in the ipc buffer.
    67 struct ParamInfo {
    68   ArgType type_;
    69   uint32 offset_;
    70   uint32 size_;
    71 };
    73 // Models the return value and the return parameters of an IPC call
    74 // currently limited to one status code and eight generic return values
    75 // which cannot be pointers to other data. For x64 ports this structure
    76 // might have to use other integer types.
    77 struct CrossCallReturn {
    78   // the IPC tag. It should match the original IPC tag.
    79   uint32 tag;
    80   // The result of the IPC operation itself.
    81   ResultCode call_outcome;
    82   // the result of the IPC call as executed in the server. The interpretation
    83   // of this value depends on the specific service.
    84   union {
    85     NTSTATUS nt_status;
    86     DWORD    win32_result;
    87   };
    88   // Number of extended return values.
    89   uint32 extended_count;
    90   // for calls that should return a windows handle. It is found here.
    91   HANDLE handle;
    92   // The array of extended values.
    93   MultiType extended[kExtendedReturnCount];
    94 };
    96 // CrossCallParams base class that models the input params all packed in a
    97 // single compact memory blob. The representation can vary but in general a
    98 // given child of this class is meant to represent all input parameters
    99 // necessary to make a IPC call.
   100 //
   101 // This class cannot have virtual members because its assumed the IPC
   102 // parameters start from the 'this' pointer to the end, which is defined by
   103 // one of the subclasses
   104 //
   105 // Objects of this class cannot be constructed directly. Only derived
   106 // classes have the proper knowledge to construct it.
   107 class CrossCallParams {
   108  public:
   109   // Returns the tag (ipc unique id) associated with this IPC.
   110   uint32 GetTag() const {
   111     return tag_;
   112   }
   114   // Returns the beggining of the buffer where the IPC params can be stored.
   115   // prior to an IPC call
   116   const void* GetBuffer() const {
   117     return this;
   118   }
   120   // Returns how many parameter this IPC call should have.
   121   const uint32 GetParamsCount() const {
   122     return params_count_;
   123   }
   125   // Returns a pointer to the CrossCallReturn structure.
   126   CrossCallReturn* GetCallReturn() {
   127     return &call_return;
   128   }
   130   // Returns TRUE if this call contains InOut parameters.
   131   const bool IsInOut() const {
   132     return (1 == is_in_out_);
   133   }
   135   // Tells the CrossCall object if it contains InOut parameters.
   136   void SetIsInOut(bool value) {
   137     if (value)
   138       is_in_out_ = 1;
   139     else
   140       is_in_out_ = 0;
   141   }
   143  protected:
   144   // constructs the IPC call params. Called only from the derived classes
   145   CrossCallParams(uint32 tag, uint32 params_count)
   146       : tag_(tag),
   147         params_count_(params_count),
   148         is_in_out_(0) {
   149   }
   151  private:
   152   uint32 tag_;
   153   uint32 is_in_out_;
   154   CrossCallReturn call_return;
   155   const uint32 params_count_;
   156   DISALLOW_COPY_AND_ASSIGN(CrossCallParams);
   157 };
   159 // ActualCallParams models an specific IPC call parameters with respect to the
   160 // storage allocation that the packed parameters should need.
   161 // NUMBER_PARAMS: the number of parameters, valid from 1 to N
   162 // BLOCK_SIZE: the total storage that the NUMBER_PARAMS parameters can take,
   163 // typically the block size is defined by the channel size of the underlying
   164 // ipc mechanism.
   165 // In practice this class is used to levergage C++ capacity to properly
   166 // calculate sizes and displacements given the possibility of the packed params
   167 // blob to be complex.
   168 //
   169 // As is, this class assumes that the layout of the blob is as follows. Assume
   170 // that NUMBER_PARAMS = 2 and a 32-bit build:
   171 //
   172 // [ tag                4 bytes]
   173 // [ IsOnOut            4 bytes]
   174 // [ call return       52 bytes]
   175 // [ params count       4 bytes]
   176 // [ parameter 0 type   4 bytes]
   177 // [ parameter 0 offset 4 bytes] ---delta to ---\
   178 // [ parameter 0 size   4 bytes]                |
   179 // [ parameter 1 type   4 bytes]                |
   180 // [ parameter 1 offset 4 bytes] ---------------|--\
   181 // [ parameter 1 size   4 bytes]                |  |
   182 // [ parameter 2 type   4 bytes]                |  |
   183 // [ parameter 2 offset 4 bytes] ----------------------\
   184 // [ parameter 2 size   4 bytes]                |  |   |
   185 // |---------------------------|                |  |   |
   186 // | value 0     (x bytes)     | <--------------/  |   |
   187 // | value 1     (y bytes)     | <-----------------/   |
   188 // |                           |                       |
   189 // | end of buffer             | <---------------------/
   190 // |---------------------------|
   191 //
   192 // Note that the actual number of params is NUMBER_PARAMS + 1
   193 // so that the size of each actual param can be computed from the difference
   194 // between one parameter and the next down. The offset of the last param
   195 // points to the end of the buffer and the type and size are undefined.
   196 //
   197 template <size_t NUMBER_PARAMS, size_t BLOCK_SIZE>
   198 class ActualCallParams : public CrossCallParams {
   199  public:
   200   // constructor. Pass the ipc unique tag as input
   201   explicit ActualCallParams(uint32 tag)
   202       : CrossCallParams(tag, NUMBER_PARAMS) {
   203     param_info_[0].offset_ = parameters_ - reinterpret_cast<char*>(this);
   204   }
   206   // Testing-only constructor. Allows setting the |number_params| to a
   207   // wrong value.
   208   ActualCallParams(uint32 tag, uint32 number_params)
   209       : CrossCallParams(tag, number_params) {
   210     param_info_[0].offset_ = parameters_ - reinterpret_cast<char*>(this);
   211   }
   213   // Testing-only method. Allows setting the apparent size to a wrong value.
   214   // returns the previous size.
   215   uint32 OverrideSize(uint32 new_size) {
   216     uint32 previous_size = param_info_[NUMBER_PARAMS].offset_;
   217     param_info_[NUMBER_PARAMS].offset_ = new_size;
   218     return previous_size;
   219   }
   221   // Copies each paramter into the internal buffer. For each you must supply:
   222   // index: 0 for the first param, 1 for the next an so on
   223   bool CopyParamIn(uint32 index, const void* parameter_address, uint32 size,
   224                    bool is_in_out, ArgType type) {
   225     if (index >= NUMBER_PARAMS) {
   226       return false;
   227     }
   229     if (kuint32max == size) {
   230       // Memory error while getting the size.
   231       return false;
   232     }
   234     if (size && !parameter_address) {
   235       return false;
   236     }
   238     if (param_info_[index].offset_ > sizeof(*this)) {
   239       // It does not fit, abort copy.
   240       return false;
   241     }
   243     char* dest = reinterpret_cast<char*>(this) +  param_info_[index].offset_;
   245     // We might be touching user memory, this has to be done from inside a try
   246     // except.
   247     __try {
   248       memcpy(dest, parameter_address, size);
   249     }
   250     __except(EXCEPTION_EXECUTE_HANDLER) {
   251       return false;
   252     }
   254     // Set the flag to tell the broker to update the buffer once the call is
   255     // made.
   256     if (is_in_out)
   257       SetIsInOut(true);
   259     param_info_[index + 1].offset_ = Align(param_info_[index].offset_ +
   260                                                 size);
   261     param_info_[index].size_ = size;
   262     param_info_[index].type_ = type;
   263     return true;
   264   }
   266   // Returns a pointer to a parameter in the memory section.
   267   void* GetParamPtr(size_t index) {
   268     return reinterpret_cast<char*>(this) + param_info_[index].offset_;
   269   }
   271   // Returns the total size of the buffer. Only valid once all the paramters
   272   // have been copied in with CopyParamIn.
   273   uint32 GetSize() const {
   274     return param_info_[NUMBER_PARAMS].offset_;
   275   }
   277  protected:
   278   ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS) { }
   280  private:
   281   ParamInfo param_info_[NUMBER_PARAMS + 1];
   282   char parameters_[BLOCK_SIZE - sizeof(CrossCallParams)
   283                    - sizeof(ParamInfo) * (NUMBER_PARAMS + 1)];
   284   DISALLOW_COPY_AND_ASSIGN(ActualCallParams);
   285 };
   287 COMPILE_ASSERT(sizeof(ActualCallParams<1, 1024>) == 1024, bad_size_buffer);
   288 COMPILE_ASSERT(sizeof(ActualCallParams<2, 1024>) == 1024, bad_size_buffer);
   289 COMPILE_ASSERT(sizeof(ActualCallParams<3, 1024>) == 1024, bad_size_buffer);
   291 }  // namespace sandbox
   293 #endif  // SANDBOX_SRC_CROSSCALL_PARAMS_H__

mercurial