Home | History | Annotate | Download | only in src
      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.
      4 
      5 #ifndef SANDBOX_SRC_CROSSCALL_SERVER_H_
      6 #define SANDBOX_SRC_CROSSCALL_SERVER_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 #include "base/basictypes.h"
     11 #include "base/callback.h"
     12 #include "base/strings/string16.h"
     13 #include "sandbox/win/src/crosscall_params.h"
     14 
     15 // This is the IPC server interface for CrossCall: The  IPC for the Sandbox
     16 // On the server, CrossCall needs two things:
     17 // 1) threads: Or better said, someone to provide them, that is what the
     18 //             ThreadProvider interface is defined for. These thread(s) are
     19 //             the ones that will actually execute the  IPC data retrieval.
     20 //
     21 // 2) a dispatcher: This interface represents the way to route and process
     22 //                  an  IPC call given the  IPC tag.
     23 //
     24 // The other class included here CrossCallParamsEx is the server side version
     25 // of the CrossCallParams class of /sandbox/crosscall_params.h The difference
     26 // is that the sever version is paranoid about the correctness of the IPC
     27 // message and will do all sorts of verifications.
     28 //
     29 // A general diagram of the interaction is as follows:
     30 //
     31 //                                 ------------
     32 //                                 |          |
     33 //  ThreadProvider <--(1)Register--|  IPC     |
     34 //      |                          | Implemen |
     35 //      |                          | -tation  |
     36 //     (2)                         |          |  OnMessage
     37 //     IPC fired --callback ------>|          |--(3)---> Dispatcher
     38 //                                 |          |
     39 //                                 ------------
     40 //
     41 //  The  IPC implementation sits as a middleman between the handling of the
     42 //  specifics of scheduling a thread to service the  IPC and the multiple
     43 //  entities that can potentially serve each particular IPC.
     44 namespace sandbox {
     45 
     46 class InterceptionManager;
     47 
     48 // This function signature is required as the callback when an  IPC call fires.
     49 // context: a user-defined pointer that was set using  ThreadProvider
     50 // reason: 0 if the callback was fired because of a timeout.
     51 //         1 if the callback was fired because of an event.
     52 typedef void (__stdcall * CrossCallIPCCallback)(void* context,
     53                                                 unsigned char reason);
     54 
     55 // ThreadProvider models a thread factory. The idea is to decouple thread
     56 // creation and lifetime from the inner guts of the IPC. The contract is
     57 // simple:
     58 //   - the IPC implementation calls RegisterWait with a waitable object that
     59 //     becomes signaled when an IPC arrives and needs to be serviced.
     60 //   - when the waitable object becomes signaled, the thread provider conjures
     61 //     a thread that calls the callback (CrossCallIPCCallback) function
     62 //   - the callback function tries its best not to block and return quickly
     63 //     and should not assume that the next callback will use the same thread
     64 //   - when the callback returns the ThreadProvider owns again the thread
     65 //     and can destroy it or keep it around.
     66 class ThreadProvider {
     67  public:
     68   // Registers a waitable object with the thread provider.
     69   // client: A number to associate with all the RegisterWait calls, typically
     70   //         this is the address of the caller object. This parameter cannot
     71   //         be zero.
     72   // waitable_object : a kernel object that can be waited on
     73   // callback: a function pointer which is the function that will be called
     74   //           when the waitable object fires
     75   // context: a user-provider pointer that is passed back to the callback
     76   //          when its called
     77   virtual bool RegisterWait(const void* client, HANDLE waitable_object,
     78                             CrossCallIPCCallback callback,
     79                             void* context) = 0;
     80 
     81   // Removes all the registrations done with the same cookie parameter.
     82   // This frees internal thread pool resources.
     83   virtual bool UnRegisterWaits(void* cookie) = 0;
     84   virtual ~ThreadProvider() {}
     85 };
     86 
     87 // Models the server-side of the original input parameters.
     88 // Provides IPC buffer validation and it is capable of reading the parameters
     89 // out of the IPC buffer.
     90 class CrossCallParamsEx : public CrossCallParams {
     91  public:
     92   // Factory constructor. Pass an IPCbuffer (and buffer size) that contains a
     93   // pending IPCcall. This constructor will:
     94   // 1) validate the IPC buffer. returns NULL is the IPCbuffer is malformed.
     95   // 2) make a copy of the IPCbuffer (parameter capture)
     96   static CrossCallParamsEx* CreateFromBuffer(void* buffer_base,
     97                                              uint32 buffer_size,
     98                                              uint32* output_size);
     99 
    100   // Provides IPCinput parameter raw access:
    101   // index : the parameter to read; 0 is the first parameter
    102   // returns NULL if the parameter is non-existent. If it exists it also
    103   // returns the size in *size
    104   void* GetRawParameter(uint32 index, uint32* size, ArgType* type);
    105 
    106   // Gets a parameter that is four bytes in size.
    107   // Returns false if the parameter does not exist or is not 32 bits wide.
    108   bool GetParameter32(uint32 index, uint32* param);
    109 
    110   // Gets a parameter that is void pointer in size.
    111   // Returns false if the parameter does not exist or is not void pointer sized.
    112   bool GetParameterVoidPtr(uint32 index, void** param);
    113 
    114   // Gets a parameter that is a string. Returns false if the parameter does not
    115   // exist.
    116   bool GetParameterStr(uint32 index, base::string16* string);
    117 
    118   // Gets a parameter that is an in/out buffer. Returns false is the parameter
    119   // does not exist or if the size of the actual parameter is not equal to the
    120   // expected size.
    121   bool GetParameterPtr(uint32 index, uint32 expected_size, void** pointer);
    122 
    123   // Frees the memory associated with the IPC parameters.
    124   static void operator delete(void* raw_memory) throw();
    125 
    126  private:
    127   // Only the factory method CreateFromBuffer can construct these objects.
    128   CrossCallParamsEx();
    129 
    130   ParamInfo param_info_[1];
    131   DISALLOW_COPY_AND_ASSIGN(CrossCallParamsEx);
    132 };
    133 
    134 // Simple helper function that sets the members of CrossCallReturn
    135 // to the proper state to signal a basic error.
    136 void SetCallError(ResultCode error, CrossCallReturn* call_return);
    137 
    138 // Sets the internal status of call_return to signify the that IPC call
    139 // completed successfully.
    140 void SetCallSuccess(CrossCallReturn* call_return);
    141 
    142 // Represents the client process that initiated the IPC which boils down to the
    143 // process handle and the job object handle that contains the client process.
    144 struct ClientInfo {
    145   HANDLE process;
    146   HANDLE job_object;
    147   DWORD process_id;
    148 };
    149 
    150 // All IPC-related information to be passed to the IPC handler.
    151 struct IPCInfo {
    152   int ipc_tag;
    153   const ClientInfo* client_info;
    154   CrossCallReturn return_info;
    155 };
    156 
    157 // This structure identifies IPC signatures.
    158 struct IPCParams {
    159   int ipc_tag;
    160   ArgType args[kMaxIpcParams];
    161 
    162   bool Matches(IPCParams* other) const {
    163     return !memcmp(this, other, sizeof(*other));
    164   }
    165 };
    166 
    167 // Models an entity that can process an IPC message or it can route to another
    168 // one that could handle it. When an IPC arrives the IPC implementation will:
    169 // 1) call OnMessageReady() with the tag of the pending IPC. If the dispatcher
    170 //    returns NULL it means that it cannot handle this IPC but if it returns
    171 //    non-null, it must be the pointer to a dispatcher that can handle it.
    172 // 2) When the  IPC finally obtains a valid Dispatcher the IPC
    173 //    implementation creates a CrossCallParamsEx from the raw IPC buffer.
    174 // 3) It calls the returned callback, with the IPC info and arguments.
    175 class Dispatcher {
    176  public:
    177   // Called from the  IPC implementation to handle a specific IPC message.
    178   typedef bool (Dispatcher::*CallbackGeneric)();
    179   typedef bool (Dispatcher::*Callback0)(IPCInfo* ipc);
    180   typedef bool (Dispatcher::*Callback1)(IPCInfo* ipc, void* p1);
    181   typedef bool (Dispatcher::*Callback2)(IPCInfo* ipc, void* p1, void* p2);
    182   typedef bool (Dispatcher::*Callback3)(IPCInfo* ipc, void* p1, void* p2,
    183                                         void* p3);
    184   typedef bool (Dispatcher::*Callback4)(IPCInfo* ipc, void* p1, void* p2,
    185                                         void* p3, void* p4);
    186   typedef bool (Dispatcher::*Callback5)(IPCInfo* ipc, void* p1, void* p2,
    187                                         void* p3, void* p4, void* p5);
    188   typedef bool (Dispatcher::*Callback6)(IPCInfo* ipc, void* p1, void* p2,
    189                                         void* p3, void* p4, void* p5, void* p6);
    190   typedef bool (Dispatcher::*Callback7)(IPCInfo* ipc, void* p1, void* p2,
    191                                         void* p3, void* p4, void* p5, void* p6,
    192                                         void* p7);
    193   typedef bool (Dispatcher::*Callback8)(IPCInfo* ipc, void* p1, void* p2,
    194                                         void* p3, void* p4, void* p5, void* p6,
    195                                         void* p7, void* p8);
    196   typedef bool (Dispatcher::*Callback9)(IPCInfo* ipc, void* p1, void* p2,
    197                                         void* p3, void* p4, void* p5, void* p6,
    198                                         void* p7, void* p8, void* p9);
    199 
    200   // Called from the  IPC implementation when an  IPC message is ready override
    201   // on a derived class to handle a set of  IPC messages. Return NULL if your
    202   // subclass does not handle the message or return the pointer to the subclass
    203   // that can handle it.
    204   virtual Dispatcher* OnMessageReady(IPCParams* ipc, CallbackGeneric* callback);
    205 
    206   // Called when a target proces is created, to setup the interceptions related
    207   // with the given service (IPC).
    208   virtual bool SetupService(InterceptionManager* manager, int service) = 0;
    209 
    210   virtual ~Dispatcher() {}
    211 
    212  protected:
    213   // Structure that defines an IPC Call with all the parameters and the handler.
    214   struct IPCCall {
    215     IPCParams params;
    216     CallbackGeneric callback;
    217   };
    218 
    219   // List of IPC Calls supported by the class.
    220   std::vector<IPCCall> ipc_calls_;
    221 };
    222 
    223 }  // namespace sandbox
    224 
    225 #endif  // SANDBOX_SRC_CROSSCALL_SERVER_H_
    226