security/sandbox/win/src/crosscall_client.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_CLIENT_H_
     6 #define SANDBOX_SRC_CROSSCALL_CLIENT_H_
     8 #include "sandbox/win/src/crosscall_params.h"
     9 #include "sandbox/win/src/sandbox.h"
    11 // This header defines the CrossCall(..) family of templated functions
    12 // Their purpose is to simulate the syntax of regular call but to generate
    13 // and IPC from the client-side.
    14 //
    15 // The basic pattern is to
    16 //   1) use template argument deduction to compute the size of each
    17 //      parameter and the appropriate copy method
    18 //   2) pack the parameters in the appropriate ActualCallParams< > object
    19 //   3) call the IPC interface IPCProvider::DoCall( )
    20 //
    21 // The general interface of CrossCall is:
    22 //  ResultCode CrossCall(IPCProvider& ipc_provider,
    23 //                       uint32 tag,
    24 //                       const Par1& p1, const Par2& p2,...pn
    25 //                       CrossCallReturn* answer)
    26 //
    27 //  where:
    28 //    ipc_provider: is a specific implementation of the ipc transport see
    29 //                  sharedmem_ipc_server.h for an example.
    30 //    tag : is the unique id for this IPC call. Is used to route the call to
    31 //          the appropriate service.
    32 //    p1, p2,.. pn : The input parameters of the IPC. Use only simple types
    33 //                   and wide strings (can add support for others).
    34 //    answer : If the IPC was successful. The server-side answer is here. The
    35 //             interpretation of the answer is private to client and server.
    36 //
    37 // The return value is ALL_OK if the IPC was delivered to the server, other
    38 // return codes indicate that the IPC transport failed to deliver it.
    39 namespace sandbox {
    41 // this is the assumed channel size. This can be overridden in a given
    42 // IPC implementation.
    43 const uint32 kIPCChannelSize = 1024;
    45 // The copy helper uses templates to deduce the appropriate copy function to
    46 // copy the input parameters in the buffer that is going to be send across the
    47 // IPC. These template facility can be made more sophisticated as need arises.
    49 // The default copy helper. It catches the general case where no other
    50 // specialized template matches better. We set the type to ULONG_TYPE, so this
    51 // only works with objects whose size is 32 bits.
    52 template<typename T>
    53 class CopyHelper {
    54  public:
    55   CopyHelper(const T& t) : t_(t) {}
    57   // Returns the pointer to the start of the input.
    58   const void* GetStart() const {
    59     return &t_;
    60   }
    62   // Update the stored value with the value in the buffer. This is not
    63   // supported for this type.
    64   bool Update(void* buffer) {
    65     // Not supported;
    66     return true;
    67   }
    69   // Returns the size of the input in bytes.
    70   uint32 GetSize() const {
    71     return sizeof(T);
    72   }
    74   // Returns true if the current type is used as an In or InOut parameter.
    75   bool IsInOut() {
    76     return false;
    77   }
    79   // Returns this object's type.
    80   ArgType GetType() {
    81     COMPILE_ASSERT(sizeof(T) == sizeof(uint32), need_specialization);
    82     return ULONG_TYPE;
    83   }
    85  private:
    86   const T& t_;
    87 };
    89 // This copy helper template specialization if for the void pointer
    90 // case both 32 and 64 bit.
    91 template<>
    92 class CopyHelper<void*> {
    93  public:
    94   CopyHelper(void* t) : t_(t) {}
    96   // Returns the pointer to the start of the input.
    97   const void* GetStart() const {
    98     return &t_;
    99   }
   101   // Update the stored value with the value in the buffer. This is not
   102   // supported for this type.
   103   bool Update(void* buffer) {
   104     // Not supported;
   105     return true;
   106   }
   108   // Returns the size of the input in bytes.
   109   uint32 GetSize() const {
   110     return sizeof(t_);
   111   }
   113   // Returns true if the current type is used as an In or InOut parameter.
   114   bool IsInOut() {
   115     return false;
   116   }
   118   // Returns this object's type.
   119   ArgType GetType() {
   120     return VOIDPTR_TYPE;
   121   }
   123  private:
   124   const void* t_;
   125 };
   127 // This copy helper template specialization catches the cases where the
   128 // parameter is a pointer to a string.
   129 template<>
   130 class CopyHelper<const wchar_t*> {
   131  public:
   132   CopyHelper(const wchar_t* t)
   133       : t_(t) {
   134   }
   136   // Returns the pointer to the start of the string.
   137   const void* GetStart() const {
   138     return t_;
   139   }
   141   // Update the stored value with the value in the buffer. This is not
   142   // supported for this type.
   143   bool Update(void* buffer) {
   144     // Not supported;
   145     return true;
   146   }
   148   // Returns the size of the string in bytes. We define a NULL string to
   149   // be of zero length.
   150   uint32 GetSize() const {
   151     __try {
   152       return (!t_) ? 0 : static_cast<uint32>(StringLength(t_) * sizeof(t_[0]));
   153     }
   154     __except(EXCEPTION_EXECUTE_HANDLER) {
   155       return kuint32max;
   156     }
   157   }
   159   // Returns true if the current type is used as an In or InOut parameter.
   160   bool IsInOut() {
   161     return false;
   162   }
   164   ArgType GetType() {
   165     return WCHAR_TYPE;
   166   }
   168  private:
   169   // We provide our not very optimized version of wcslen(), since we don't
   170   // want to risk having the linker use the version in the CRT since the CRT
   171   // might not be present when we do an early IPC call.
   172   static size_t __cdecl StringLength(const wchar_t* wcs) {
   173     const wchar_t *eos = wcs;
   174     while (*eos++);
   175     return static_cast<size_t>(eos - wcs - 1);
   176   }
   178   const wchar_t* t_;
   179 };
   181 // Specialization for non-const strings. We just reuse the implementation of the
   182 // const string specialization.
   183 template<>
   184 class CopyHelper<wchar_t*> : public CopyHelper<const wchar_t*> {
   185  public:
   186   typedef CopyHelper<const wchar_t*> Base;
   187   CopyHelper(wchar_t* t) : Base(t) {}
   189   const void* GetStart() const {
   190     return Base::GetStart();
   191   }
   193   bool Update(void* buffer) {
   194     return Base::Update(buffer);
   195   }
   197   uint32 GetSize() const {
   198     return Base::GetSize();
   199   }
   201   bool IsInOut() {
   202     return Base::IsInOut();
   203   }
   205   ArgType GetType() {
   206     return Base::GetType();
   207   }
   208 };
   210 // Specialization for wchar_t arrays strings. We just reuse the implementation
   211 // of the const string specialization.
   212 template<size_t n>
   213 class CopyHelper<const wchar_t[n]> : public CopyHelper<const wchar_t*> {
   214  public:
   215   typedef const wchar_t array[n];
   216   typedef CopyHelper<const wchar_t*> Base;
   217   CopyHelper(array t) : Base(t) {}
   219   const void* GetStart() const {
   220     return Base::GetStart();
   221   }
   223   bool Update(void* buffer) {
   224     return Base::Update(buffer);
   225   }
   227   uint32 GetSize() const {
   228     return Base::GetSize();
   229   }
   231   bool IsInOut() {
   232     return Base::IsInOut();
   233   }
   235   ArgType GetType() {
   236     return Base::GetType();
   237   }
   238 };
   240 // Generic encapsulation class containing a pointer to a buffer and the
   241 // size of the buffer. It is used by the IPC to be able to pass in/out
   242 // parameters.
   243 class InOutCountedBuffer : public CountedBuffer {
   244  public:
   245   InOutCountedBuffer(void* buffer, uint32 size) : CountedBuffer(buffer, size) {}
   246 };
   248 // This copy helper template specialization catches the cases where the
   249 // parameter is a an input/output buffer.
   250 template<>
   251 class CopyHelper<InOutCountedBuffer> {
   252  public:
   253   CopyHelper(const InOutCountedBuffer t) : t_(t) {}
   255   // Returns the pointer to the start of the string.
   256   const void* GetStart() const {
   257     return t_.Buffer();
   258   }
   260   // Updates the buffer with the value from the new buffer in parameter.
   261   bool Update(void* buffer) {
   262     // We are touching user memory, this has to be done from inside a try
   263     // except.
   264     __try {
   265       memcpy(t_.Buffer(), buffer, t_.Size());
   266     }
   267     __except(EXCEPTION_EXECUTE_HANDLER) {
   268       return false;
   269     }
   270     return true;
   271   }
   273   // Returns the size of the string in bytes. We define a NULL string to
   274   // be of zero length.
   275   uint32 GetSize() const {
   276     return t_.Size();
   277   }
   279   // Returns true if the current type is used as an In or InOut parameter.
   280   bool IsInOut() {
   281     return true;
   282   }
   284   ArgType GetType() {
   285     return INOUTPTR_TYPE;
   286   }
   288  private:
   289   const InOutCountedBuffer t_;
   290 };
   292 // The following two macros make it less error prone the generation
   293 // of CrossCall functions with ever more input parameters.
   295 #define XCALL_GEN_PARAMS_OBJ(num, params) \
   296   typedef ActualCallParams<num, kIPCChannelSize> ActualParams; \
   297   void* raw_mem = ipc_provider.GetBuffer(); \
   298   if (NULL == raw_mem) \
   299     return SBOX_ERROR_NO_SPACE; \
   300   ActualParams* params = new(raw_mem) ActualParams(tag);
   302 #define XCALL_GEN_COPY_PARAM(num, params) \
   303   COMPILE_ASSERT(kMaxIpcParams >= num, too_many_parameters); \
   304   CopyHelper<Par##num> ch##num(p##num); \
   305   if (!params->CopyParamIn(num - 1, ch##num.GetStart(), ch##num.GetSize(), \
   306                            ch##num.IsInOut(), ch##num.GetType())) \
   307     return SBOX_ERROR_NO_SPACE;
   309 #define XCALL_GEN_UPDATE_PARAM(num, params) \
   310   if (!ch##num.Update(params->GetParamPtr(num-1))) {\
   311     ipc_provider.FreeBuffer(raw_mem); \
   312     return SBOX_ERROR_BAD_PARAMS; \
   313   }
   315 #define XCALL_GEN_FREE_CHANNEL() \
   316   ipc_provider.FreeBuffer(raw_mem);
   318 // CrossCall template with one input parameter
   319 template <typename IPCProvider, typename Par1>
   320 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   321                      CrossCallReturn* answer) {
   322   XCALL_GEN_PARAMS_OBJ(1, call_params);
   323   XCALL_GEN_COPY_PARAM(1, call_params);
   325   ResultCode result = ipc_provider.DoCall(call_params, answer);
   327   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   328     XCALL_GEN_UPDATE_PARAM(1, call_params);
   329     XCALL_GEN_FREE_CHANNEL();
   330   }
   332   return result;
   333 }
   335 // CrossCall template with two input parameters.
   336 template <typename IPCProvider, typename Par1, typename Par2>
   337 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   338                      const Par2& p2, CrossCallReturn* answer) {
   339   XCALL_GEN_PARAMS_OBJ(2, call_params);
   340   XCALL_GEN_COPY_PARAM(1, call_params);
   341   XCALL_GEN_COPY_PARAM(2, call_params);
   343   ResultCode result = ipc_provider.DoCall(call_params, answer);
   345   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   346     XCALL_GEN_UPDATE_PARAM(1, call_params);
   347     XCALL_GEN_UPDATE_PARAM(2, call_params);
   348     XCALL_GEN_FREE_CHANNEL();
   349   }
   350   return result;
   351 }
   353 // CrossCall template with three input parameters.
   354 template <typename IPCProvider, typename Par1, typename Par2, typename Par3>
   355 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   356                      const Par2& p2, const Par3& p3, CrossCallReturn* answer) {
   357   XCALL_GEN_PARAMS_OBJ(3, call_params);
   358   XCALL_GEN_COPY_PARAM(1, call_params);
   359   XCALL_GEN_COPY_PARAM(2, call_params);
   360   XCALL_GEN_COPY_PARAM(3, call_params);
   362   ResultCode result = ipc_provider.DoCall(call_params, answer);
   364   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   365     XCALL_GEN_UPDATE_PARAM(1, call_params);
   366     XCALL_GEN_UPDATE_PARAM(2, call_params);
   367     XCALL_GEN_UPDATE_PARAM(3, call_params);
   368     XCALL_GEN_FREE_CHANNEL();
   369   }
   370   return result;
   371 }
   373 // CrossCall template with four input parameters.
   374 template <typename IPCProvider, typename Par1, typename Par2, typename Par3,
   375           typename Par4>
   376 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   377                      const Par2& p2, const Par3& p3, const Par4& p4,
   378                      CrossCallReturn* answer) {
   379   XCALL_GEN_PARAMS_OBJ(4, call_params);
   380   XCALL_GEN_COPY_PARAM(1, call_params);
   381   XCALL_GEN_COPY_PARAM(2, call_params);
   382   XCALL_GEN_COPY_PARAM(3, call_params);
   383   XCALL_GEN_COPY_PARAM(4, call_params);
   385   ResultCode result = ipc_provider.DoCall(call_params, answer);
   387   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   388     XCALL_GEN_UPDATE_PARAM(1, call_params);
   389     XCALL_GEN_UPDATE_PARAM(2, call_params);
   390     XCALL_GEN_UPDATE_PARAM(3, call_params);
   391     XCALL_GEN_UPDATE_PARAM(4, call_params);
   392     XCALL_GEN_FREE_CHANNEL();
   393   }
   394   return result;
   395 }
   397 // CrossCall template with five input parameters.
   398 template <typename IPCProvider, typename Par1, typename Par2, typename Par3,
   399           typename Par4, typename Par5>
   400 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   401                      const Par2& p2, const Par3& p3, const Par4& p4,
   402                      const Par5& p5, CrossCallReturn* answer) {
   403   XCALL_GEN_PARAMS_OBJ(5, call_params);
   404   XCALL_GEN_COPY_PARAM(1, call_params);
   405   XCALL_GEN_COPY_PARAM(2, call_params);
   406   XCALL_GEN_COPY_PARAM(3, call_params);
   407   XCALL_GEN_COPY_PARAM(4, call_params);
   408   XCALL_GEN_COPY_PARAM(5, call_params);
   410   ResultCode result = ipc_provider.DoCall(call_params, answer);
   412   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   413     XCALL_GEN_UPDATE_PARAM(1, call_params);
   414     XCALL_GEN_UPDATE_PARAM(2, call_params);
   415     XCALL_GEN_UPDATE_PARAM(3, call_params);
   416     XCALL_GEN_UPDATE_PARAM(4, call_params);
   417     XCALL_GEN_UPDATE_PARAM(5, call_params);
   418     XCALL_GEN_FREE_CHANNEL();
   419   }
   420   return result;
   421 }
   423 // CrossCall template with six input parameters.
   424 template <typename IPCProvider, typename Par1, typename Par2, typename Par3,
   425           typename Par4, typename Par5, typename Par6>
   426 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   427                      const Par2& p2, const Par3& p3, const Par4& p4,
   428                      const Par5& p5, const Par6& p6, CrossCallReturn* answer) {
   429   XCALL_GEN_PARAMS_OBJ(6, call_params);
   430   XCALL_GEN_COPY_PARAM(1, call_params);
   431   XCALL_GEN_COPY_PARAM(2, call_params);
   432   XCALL_GEN_COPY_PARAM(3, call_params);
   433   XCALL_GEN_COPY_PARAM(4, call_params);
   434   XCALL_GEN_COPY_PARAM(5, call_params);
   435   XCALL_GEN_COPY_PARAM(6, call_params);
   437   ResultCode result = ipc_provider.DoCall(call_params, answer);
   439   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   440     XCALL_GEN_UPDATE_PARAM(1, call_params);
   441     XCALL_GEN_UPDATE_PARAM(2, call_params);
   442     XCALL_GEN_UPDATE_PARAM(3, call_params);
   443     XCALL_GEN_UPDATE_PARAM(4, call_params);
   444     XCALL_GEN_UPDATE_PARAM(5, call_params);
   445     XCALL_GEN_UPDATE_PARAM(6, call_params);
   446     XCALL_GEN_FREE_CHANNEL();
   447   }
   448   return result;
   449 }
   451 // CrossCall template with seven input parameters.
   452 template <typename IPCProvider, typename Par1, typename Par2, typename Par3,
   453           typename Par4, typename Par5, typename Par6, typename Par7>
   454 ResultCode CrossCall(IPCProvider& ipc_provider, uint32 tag, const Par1& p1,
   455                      const Par2& p2, const Par3& p3, const Par4& p4,
   456                      const Par5& p5, const Par6& p6, const Par7& p7,
   457                      CrossCallReturn* answer) {
   458   XCALL_GEN_PARAMS_OBJ(7, call_params);
   459   XCALL_GEN_COPY_PARAM(1, call_params);
   460   XCALL_GEN_COPY_PARAM(2, call_params);
   461   XCALL_GEN_COPY_PARAM(3, call_params);
   462   XCALL_GEN_COPY_PARAM(4, call_params);
   463   XCALL_GEN_COPY_PARAM(5, call_params);
   464   XCALL_GEN_COPY_PARAM(6, call_params);
   465   XCALL_GEN_COPY_PARAM(7, call_params);
   467   ResultCode result = ipc_provider.DoCall(call_params, answer);
   469   if (SBOX_ERROR_CHANNEL_ERROR != result) {
   470     XCALL_GEN_UPDATE_PARAM(1, call_params);
   471     XCALL_GEN_UPDATE_PARAM(2, call_params);
   472     XCALL_GEN_UPDATE_PARAM(3, call_params);
   473     XCALL_GEN_UPDATE_PARAM(4, call_params);
   474     XCALL_GEN_UPDATE_PARAM(5, call_params);
   475     XCALL_GEN_UPDATE_PARAM(6, call_params);
   476     XCALL_GEN_UPDATE_PARAM(7, call_params);
   477     XCALL_GEN_FREE_CHANNEL();
   478   }
   479   return result;
   480 }
   481 }  // namespace sandbox
   483 #endif  // SANDBOX_SRC_CROSSCALL_CLIENT_H__

mercurial