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 #include "base/callback.h"
      6 #include "base/logging.h"
      7 #include "base/memory/scoped_ptr.h"
      8 #include "sandbox/win/src/sharedmem_ipc_server.h"
      9 #include "sandbox/win/src/sharedmem_ipc_client.h"
     10 #include "sandbox/win/src/sandbox.h"
     11 #include "sandbox/win/src/sandbox_types.h"
     12 #include "sandbox/win/src/crosscall_params.h"
     13 #include "sandbox/win/src/crosscall_server.h"
     14 
     15 namespace {
     16 // This handle must not be closed.
     17 volatile HANDLE g_alive_mutex = NULL;
     18 }
     19 
     20 namespace sandbox {
     21 
     22 SharedMemIPCServer::SharedMemIPCServer(HANDLE target_process,
     23                                        DWORD target_process_id,
     24                                        HANDLE target_job,
     25                                        ThreadProvider* thread_provider,
     26                                        Dispatcher* dispatcher)
     27     : client_control_(NULL),
     28       thread_provider_(thread_provider),
     29       target_process_(target_process),
     30       target_process_id_(target_process_id),
     31       target_job_object_(target_job),
     32       call_dispatcher_(dispatcher) {
     33   // We create a initially owned mutex. If the server dies unexpectedly,
     34   // the thread that owns it will fail to release the lock and windows will
     35   // report to the target (when it tries to acquire it) that the wait was
     36   // abandoned. Note: We purposely leak the local handle because we want it to
     37   // be closed by Windows itself so it is properly marked as abandoned if the
     38   // server dies.
     39   if (!g_alive_mutex) {
     40     HANDLE mutex = ::CreateMutexW(NULL, TRUE, NULL);
     41     if (::InterlockedCompareExchangePointer(&g_alive_mutex, mutex, NULL)) {
     42       // We lost the race to create the mutex.
     43       ::CloseHandle(mutex);
     44     }
     45   }
     46 }
     47 
     48 SharedMemIPCServer::~SharedMemIPCServer() {
     49   // Free the wait handles associated with the thread pool.
     50   if (!thread_provider_->UnRegisterWaits(this)) {
     51     // Better to leak than to crash.
     52     return;
     53   }
     54   // Free the IPC signal events.
     55   ServerContexts::iterator it;
     56   for (it = server_contexts_.begin(); it != server_contexts_.end(); ++it) {
     57     ServerControl* context = (*it);
     58     ::CloseHandle(context->ping_event);
     59     ::CloseHandle(context->pong_event);
     60     delete context;
     61   }
     62 }
     63 
     64 bool SharedMemIPCServer::Init(void* shared_mem, uint32 shared_size,
     65                               uint32 channel_size) {
     66   // The shared memory needs to be at least as big as a channel.
     67   if (shared_size < channel_size) {
     68     return false;
     69   }
     70   // The channel size should be aligned.
     71   if (0 != (channel_size % 32)) {
     72     return false;
     73   }
     74 
     75   // Calculate how many channels we can fit in the shared memory.
     76   shared_size -= offsetof(IPCControl, channels);
     77   size_t channel_count = shared_size / (sizeof(ChannelControl) + channel_size);
     78 
     79   // If we cannot fit even one channel we bail out.
     80   if (0 == channel_count) {
     81     return false;
     82   }
     83   // Calculate the start of the first channel.
     84   size_t base_start = (sizeof(ChannelControl)* channel_count) +
     85                        offsetof(IPCControl, channels);
     86 
     87   client_control_ = reinterpret_cast<IPCControl*>(shared_mem);
     88   client_control_->channels_count = 0;
     89 
     90   // This is the initialization that we do per-channel. Basically:
     91   // 1) make two events (ping & pong)
     92   // 2) create handles to the events for the client and the server.
     93   // 3) initialize the channel (client_context) with the state.
     94   // 4) initialize the server side of the channel (service_context).
     95   // 5) call the thread provider RegisterWait to register the ping events.
     96   for (size_t ix = 0; ix != channel_count; ++ix) {
     97     ChannelControl* client_context = &client_control_->channels[ix];
     98     ServerControl* service_context = new ServerControl;
     99     server_contexts_.push_back(service_context);
    100 
    101     if (!MakeEvents(&service_context->ping_event,
    102                     &service_context->pong_event,
    103                     &client_context->ping_event,
    104                     &client_context->pong_event)) {
    105       return false;
    106     }
    107 
    108     client_context->channel_base = base_start;
    109     client_context->state = kFreeChannel;
    110 
    111     // Note that some of these values are available as members of this
    112     // object but we put them again into the service_context because we
    113     // will be called on a static method (ThreadPingEventReady)
    114     service_context->shared_base = reinterpret_cast<char*>(shared_mem);
    115     service_context->channel_size = channel_size;
    116     service_context->channel = client_context;
    117     service_context->channel_buffer = service_context->shared_base +
    118                                       client_context->channel_base;
    119     service_context->dispatcher = call_dispatcher_;
    120     service_context->target_info.process = target_process_;
    121     service_context->target_info.process_id = target_process_id_;
    122     service_context->target_info.job_object = target_job_object_;
    123     // Advance to the next channel.
    124     base_start += channel_size;
    125     // Register the ping event with the threadpool.
    126     thread_provider_->RegisterWait(this, service_context->ping_event,
    127                                    ThreadPingEventReady, service_context);
    128   }
    129   if (!::DuplicateHandle(::GetCurrentProcess(), g_alive_mutex,
    130                          target_process_, &client_control_->server_alive,
    131                          SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, 0)) {
    132     return false;
    133   }
    134   // This last setting indicates to the client all is setup.
    135   client_control_->channels_count = channel_count;
    136   return true;
    137 }
    138 
    139 // Releases memory allocated for IPC arguments, if needed.
    140 void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) {
    141   for (size_t i = 0; i < kMaxIpcParams; i++) {
    142     switch (ipc_params->args[i]) {
    143       case WCHAR_TYPE: {
    144         delete reinterpret_cast<base::string16*>(args[i]);
    145         args[i] = NULL;
    146         break;
    147       }
    148       case INOUTPTR_TYPE: {
    149         delete reinterpret_cast<CountedBuffer*>(args[i]);
    150         args[i] = NULL;
    151         break;
    152       }
    153       default: break;
    154     }
    155   }
    156 }
    157 
    158 // Fills up the list of arguments (args and ipc_params) for an IPC call.
    159 bool GetArgs(CrossCallParamsEx* params, IPCParams* ipc_params,
    160              void* args[kMaxIpcParams]) {
    161   if (kMaxIpcParams < params->GetParamsCount())
    162     return false;
    163 
    164   for (uint32 i = 0; i < params->GetParamsCount(); i++) {
    165     uint32 size;
    166     ArgType type;
    167     args[i] = params->GetRawParameter(i, &size, &type);
    168     if (args[i]) {
    169       ipc_params->args[i] = type;
    170       switch (type) {
    171         case WCHAR_TYPE: {
    172           scoped_ptr<base::string16> data(new base::string16);
    173           if (!params->GetParameterStr(i, data.get())) {
    174             args[i] = 0;
    175             ReleaseArgs(ipc_params, args);
    176             return false;
    177           }
    178           args[i] = data.release();
    179           break;
    180         }
    181         case ULONG_TYPE: {
    182           uint32 data;
    183           if (!params->GetParameter32(i, &data)) {
    184             ReleaseArgs(ipc_params, args);
    185             return false;
    186           }
    187           IPCInt ipc_int(data);
    188           args[i] = ipc_int.AsVoidPtr();
    189           break;
    190         }
    191         case VOIDPTR_TYPE : {
    192           void* data;
    193           if (!params->GetParameterVoidPtr(i, &data)) {
    194             ReleaseArgs(ipc_params, args);
    195             return false;
    196           }
    197           args[i] = data;
    198           break;
    199         }
    200         case INOUTPTR_TYPE: {
    201           if (!args[i]) {
    202             ReleaseArgs(ipc_params, args);
    203             return false;
    204           }
    205           CountedBuffer* buffer = new CountedBuffer(args[i] , size);
    206           args[i] = buffer;
    207           break;
    208         }
    209         default: break;
    210       }
    211     }
    212   }
    213   return true;
    214 }
    215 
    216 bool SharedMemIPCServer::InvokeCallback(const ServerControl* service_context,
    217                                         void* ipc_buffer,
    218                                         CrossCallReturn* call_result) {
    219   // Set the default error code;
    220   SetCallError(SBOX_ERROR_INVALID_IPC, call_result);
    221   uint32 output_size = 0;
    222   // Parse, verify and copy the message. The handler operates on a copy
    223   // of the message so the client cannot play dirty tricks by changing the
    224   // data in the channel while the IPC is being processed.
    225   scoped_ptr<CrossCallParamsEx> params(
    226       CrossCallParamsEx::CreateFromBuffer(ipc_buffer,
    227                                           service_context->channel_size,
    228                                           &output_size));
    229   if (!params.get())
    230     return false;
    231 
    232   uint32 tag = params->GetTag();
    233   COMPILE_ASSERT(0 == INVALID_TYPE, Incorrect_type_enum);
    234   IPCParams ipc_params = {0};
    235   ipc_params.ipc_tag = tag;
    236 
    237   void* args[kMaxIpcParams];
    238   if (!GetArgs(params.get(), &ipc_params, args))
    239     return false;
    240 
    241   IPCInfo ipc_info = {0};
    242   ipc_info.ipc_tag = tag;
    243   ipc_info.client_info = &service_context->target_info;
    244   Dispatcher* dispatcher = service_context->dispatcher;
    245   DCHECK(dispatcher);
    246   bool error = true;
    247   Dispatcher* handler = NULL;
    248 
    249   Dispatcher::CallbackGeneric callback_generic;
    250   handler = dispatcher->OnMessageReady(&ipc_params, &callback_generic);
    251   if (handler) {
    252     switch (params->GetParamsCount()) {
    253       case 0: {
    254         // Ask the IPC dispatcher if she can service this IPC.
    255         Dispatcher::Callback0 callback =
    256             reinterpret_cast<Dispatcher::Callback0>(callback_generic);
    257         if (!(handler->*callback)(&ipc_info))
    258           break;
    259         error = false;
    260         break;
    261       }
    262       case 1: {
    263         Dispatcher::Callback1 callback =
    264             reinterpret_cast<Dispatcher::Callback1>(callback_generic);
    265         if (!(handler->*callback)(&ipc_info, args[0]))
    266           break;
    267         error = false;
    268         break;
    269       }
    270       case 2: {
    271         Dispatcher::Callback2 callback =
    272             reinterpret_cast<Dispatcher::Callback2>(callback_generic);
    273         if (!(handler->*callback)(&ipc_info, args[0], args[1]))
    274           break;
    275         error = false;
    276         break;
    277       }
    278       case 3: {
    279         Dispatcher::Callback3 callback =
    280             reinterpret_cast<Dispatcher::Callback3>(callback_generic);
    281         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2]))
    282           break;
    283         error = false;
    284         break;
    285       }
    286       case 4: {
    287         Dispatcher::Callback4 callback =
    288             reinterpret_cast<Dispatcher::Callback4>(callback_generic);
    289         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2],
    290                                   args[3]))
    291           break;
    292         error = false;
    293         break;
    294       }
    295       case 5: {
    296         Dispatcher::Callback5 callback =
    297             reinterpret_cast<Dispatcher::Callback5>(callback_generic);
    298         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
    299                                   args[4]))
    300           break;
    301         error = false;
    302         break;
    303       }
    304       case 6: {
    305         Dispatcher::Callback6 callback =
    306             reinterpret_cast<Dispatcher::Callback6>(callback_generic);
    307         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
    308                                   args[4], args[5]))
    309           break;
    310         error = false;
    311         break;
    312       }
    313       case 7: {
    314         Dispatcher::Callback7 callback =
    315             reinterpret_cast<Dispatcher::Callback7>(callback_generic);
    316         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
    317                                   args[4], args[5], args[6]))
    318           break;
    319         error = false;
    320         break;
    321       }
    322       case 8: {
    323         Dispatcher::Callback8 callback =
    324             reinterpret_cast<Dispatcher::Callback8>(callback_generic);
    325         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
    326                                   args[4], args[5], args[6], args[7]))
    327           break;
    328         error = false;
    329         break;
    330       }
    331       case 9: {
    332         Dispatcher::Callback9 callback =
    333             reinterpret_cast<Dispatcher::Callback9>(callback_generic);
    334         if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
    335                                   args[4], args[5], args[6], args[7], args[8]))
    336           break;
    337         error = false;
    338         break;
    339       }
    340       default:  {
    341         NOTREACHED();
    342         break;
    343       }
    344     }
    345   }
    346 
    347   if (error) {
    348     if (handler)
    349       SetCallError(SBOX_ERROR_FAILED_IPC, call_result);
    350   } else {
    351     memcpy(call_result, &ipc_info.return_info, sizeof(*call_result));
    352     SetCallSuccess(call_result);
    353     if (params->IsInOut()) {
    354       // Maybe the params got changed by the broker. We need to upadte the
    355       // memory section.
    356       memcpy(ipc_buffer, params.get(), output_size);
    357     }
    358   }
    359 
    360   ReleaseArgs(&ipc_params, args);
    361 
    362   return !error;
    363 }
    364 
    365 // This function gets called by a thread from the thread pool when a
    366 // ping event fires. The context is the same as passed in the RegisterWait()
    367 // call above.
    368 void __stdcall SharedMemIPCServer::ThreadPingEventReady(void* context,
    369                                                         unsigned char) {
    370   if (NULL == context) {
    371     DCHECK(false);
    372     return;
    373   }
    374   ServerControl* service_context = reinterpret_cast<ServerControl*>(context);
    375   // Since the event fired, the channel *must* be busy. Change to kAckChannel
    376   // while we service it.
    377   LONG last_state =
    378     ::InterlockedCompareExchange(&service_context->channel->state,
    379                                  kAckChannel, kBusyChannel);
    380   if (kBusyChannel != last_state) {
    381     DCHECK(false);
    382     return;
    383   }
    384 
    385   // Prepare the result structure. At this point we will return some result
    386   // even if the IPC is invalid, malformed or has no handler.
    387   CrossCallReturn call_result = {0};
    388   void* buffer = service_context->channel_buffer;
    389 
    390   InvokeCallback(service_context, buffer, &call_result);
    391 
    392   // Copy the answer back into the channel and signal the pong event. This
    393   // should wake up the client so he can finish the the ipc cycle.
    394   CrossCallParams* call_params = reinterpret_cast<CrossCallParams*>(buffer);
    395   memcpy(call_params->GetCallReturn(), &call_result, sizeof(call_result));
    396   ::InterlockedExchange(&service_context->channel->state, kAckChannel);
    397   ::SetEvent(service_context->pong_event);
    398 }
    399 
    400 bool SharedMemIPCServer::MakeEvents(HANDLE* server_ping, HANDLE* server_pong,
    401                                     HANDLE* client_ping, HANDLE* client_pong) {
    402   // Note that the IPC client has no right to delete the events. That would
    403   // cause problems. The server *owns* the events.
    404   const DWORD kDesiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE;
    405 
    406   // The events are auto reset, and start not signaled.
    407   *server_ping = ::CreateEventW(NULL, FALSE, FALSE, NULL);
    408   if (!::DuplicateHandle(::GetCurrentProcess(), *server_ping, target_process_,
    409                          client_ping, kDesiredAccess, FALSE, 0)) {
    410     return false;
    411   }
    412   *server_pong = ::CreateEventW(NULL, FALSE, FALSE, NULL);
    413   if (!::DuplicateHandle(::GetCurrentProcess(), *server_pong, target_process_,
    414                          client_pong, kDesiredAccess, FALSE, 0)) {
    415     return false;
    416   }
    417   return true;
    418 }
    419 
    420 }  // namespace sandbox
    421