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/basictypes.h"
      6 #include "sandbox/win/src/crosscall_client.h"
      7 #include "sandbox/win/src/crosscall_server.h"
      8 #include "sandbox/win/src/sharedmem_ipc_client.h"
      9 #include "sandbox/win/src/sharedmem_ipc_server.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace sandbox {
     13 
     14 // Helper function to make the fake shared memory with some
     15 // basic elements initialized.
     16 IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size,
     17                          size_t* base_start) {
     18   // Allocate memory
     19   char* mem = new char[total_shared_size];
     20   memset(mem, 0, total_shared_size);
     21   // Calculate how many channels we can fit in the shared memory.
     22   total_shared_size -= offsetof(IPCControl, channels);
     23   size_t channel_count =
     24     total_shared_size / (sizeof(ChannelControl) + channel_size);
     25   // Calculate the start of the first channel.
     26   *base_start = (sizeof(ChannelControl)* channel_count) +
     27     offsetof(IPCControl, channels);
     28   // Setup client structure.
     29   IPCControl* client_control = reinterpret_cast<IPCControl*>(mem);
     30   client_control->channels_count = channel_count;
     31   return client_control;
     32 }
     33 
     34 enum TestFixMode {
     35   FIX_NO_EVENTS,
     36   FIX_PONG_READY,
     37   FIX_PONG_NOT_READY
     38 };
     39 
     40 void FixChannels(IPCControl* client_control, size_t base_start,
     41                  size_t channel_size, TestFixMode mode) {
     42   for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
     43     ChannelControl& channel = client_control->channels[ix];
     44     channel.channel_base = base_start;
     45     channel.state = kFreeChannel;
     46     if (mode != FIX_NO_EVENTS) {
     47       BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE;
     48       channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL);
     49       channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL);
     50     }
     51     base_start += channel_size;
     52   }
     53 }
     54 
     55 void CloseChannelEvents(IPCControl* client_control) {
     56   for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
     57     ChannelControl& channel = client_control->channels[ix];
     58     ::CloseHandle(channel.ping_event);
     59     ::CloseHandle(channel.pong_event);
     60   }
     61 }
     62 
     63 TEST(IPCTest, ChannelMaker) {
     64   // Test that our testing rig is computing offsets properly. We should have
     65   // 5 channnels and the offset to the first channel is 108 bytes in 32 bits
     66   // and 216 in 64 bits.
     67   size_t channel_start = 0;
     68   IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start);
     69   ASSERT_TRUE(NULL != client_control);
     70   EXPECT_EQ(5, client_control->channels_count);
     71 #if defined(_WIN64)
     72   EXPECT_EQ(216, channel_start);
     73 #else
     74   EXPECT_EQ(108, channel_start);
     75 #endif
     76   delete[] reinterpret_cast<char*>(client_control);
     77 }
     78 
     79 TEST(IPCTest, ClientLockUnlock) {
     80   // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and
     81   // unlock channels properly.
     82   size_t base_start = 0;
     83   IPCControl* client_control =
     84       MakeChannels(kIPCChannelSize, 4096 * 2, &base_start);
     85   FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS);
     86 
     87   char* mem = reinterpret_cast<char*>(client_control);
     88   SharedMemIPCClient client(mem);
     89 
     90   // Test that we lock the first 3 channels in sequence.
     91   void* buff0 = client.GetBuffer();
     92   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
     93   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
     94   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
     95   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
     96   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
     97   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
     98   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
     99 
    100   void* buff1 = client.GetBuffer();
    101   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
    102   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    103   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    104   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    105   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
    106   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
    107   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
    108 
    109   void* buff2 = client.GetBuffer();
    110   EXPECT_TRUE(mem + client_control->channels[2].channel_base == buff2);
    111   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    112   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    113   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
    114   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
    115   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
    116   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
    117 
    118   // Test that we unlock and re-lock the right channel.
    119   client.FreeBuffer(buff1);
    120   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    121   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    122   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
    123   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
    124   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
    125   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
    126 
    127   void* buff2b = client.GetBuffer();
    128   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff2b);
    129   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    130   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    131   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
    132   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
    133   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
    134   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
    135 
    136   client.FreeBuffer(buff0);
    137   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
    138   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    139   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
    140   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
    141   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
    142   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
    143 
    144   delete[] reinterpret_cast<char*>(client_control);
    145 }
    146 
    147 TEST(IPCTest, CrossCallStrPacking) {
    148   // This test tries the CrossCall object with null and non-null string
    149   // combination of parameters, integer types and verifies that the unpacker
    150   // can read them properly.
    151   size_t base_start = 0;
    152   IPCControl* client_control =
    153       MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
    154   client_control->server_alive = HANDLE(1);
    155   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
    156 
    157   char* mem = reinterpret_cast<char*>(client_control);
    158   SharedMemIPCClient client(mem);
    159 
    160   CrossCallReturn answer;
    161   uint32 tag1 = 666;
    162   const wchar_t *text = L"98765 - 43210";
    163   base::string16 copied_text;
    164   CrossCallParamsEx* actual_params;
    165 
    166   CrossCall(client, tag1, text, &answer);
    167   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    168   EXPECT_EQ(1, actual_params->GetParamsCount());
    169   EXPECT_EQ(tag1, actual_params->GetTag());
    170   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
    171   EXPECT_STREQ(text, copied_text.c_str());
    172 
    173   // Check with an empty string.
    174   uint32 tag2 = 777;
    175   const wchar_t* null_text = NULL;
    176   CrossCall(client, tag2, null_text, &answer);
    177   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    178   EXPECT_EQ(1, actual_params->GetParamsCount());
    179   EXPECT_EQ(tag2, actual_params->GetTag());
    180   uint32 param_size = 1;
    181   ArgType type = INVALID_TYPE;
    182   void* param_addr = actual_params->GetRawParameter(0, &param_size, &type);
    183   EXPECT_TRUE(NULL != param_addr);
    184   EXPECT_EQ(0, param_size);
    185   EXPECT_EQ(WCHAR_TYPE, type);
    186   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
    187 
    188   uint32 tag3 = 888;
    189   param_size = 1;
    190   copied_text.clear();
    191 
    192   // Check with an empty string and a non-empty string.
    193   CrossCall(client, tag3, null_text, text, &answer);
    194   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    195   EXPECT_EQ(2, actual_params->GetParamsCount());
    196   EXPECT_EQ(tag3, actual_params->GetTag());
    197   type = INVALID_TYPE;
    198   param_addr = actual_params->GetRawParameter(0, &param_size, &type);
    199   EXPECT_TRUE(NULL != param_addr);
    200   EXPECT_EQ(0, param_size);
    201   EXPECT_EQ(WCHAR_TYPE, type);
    202   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
    203   EXPECT_TRUE(actual_params->GetParameterStr(1, &copied_text));
    204   EXPECT_STREQ(text, copied_text.c_str());
    205 
    206   param_size = 1;
    207   base::string16 copied_text_p0, copied_text_p2;
    208 
    209   const wchar_t *text2 = L"AeFG";
    210   CrossCall(client, tag1, text2, null_text, text, &answer);
    211   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    212   EXPECT_EQ(3, actual_params->GetParamsCount());
    213   EXPECT_EQ(tag1, actual_params->GetTag());
    214   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text_p0));
    215   EXPECT_STREQ(text2, copied_text_p0.c_str());
    216   EXPECT_TRUE(actual_params->GetParameterStr(2, &copied_text_p2));
    217   EXPECT_STREQ(text, copied_text_p2.c_str());
    218   type = INVALID_TYPE;
    219   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
    220   EXPECT_TRUE(NULL != param_addr);
    221   EXPECT_EQ(0, param_size);
    222   EXPECT_EQ(WCHAR_TYPE, type);
    223 
    224   CloseChannelEvents(client_control);
    225   delete[] reinterpret_cast<char*>(client_control);
    226 }
    227 
    228 TEST(IPCTest, CrossCallIntPacking) {
    229   // Check handling for regular 32 bit integers used in Windows.
    230   size_t base_start = 0;
    231   IPCControl* client_control =
    232       MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
    233   client_control->server_alive = HANDLE(1);
    234   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
    235 
    236   uint32 tag1 = 999;
    237   uint32 tag2 = 111;
    238   const wchar_t *text = L"godzilla";
    239   CrossCallParamsEx* actual_params;
    240 
    241   char* mem = reinterpret_cast<char*>(client_control);
    242   SharedMemIPCClient client(mem);
    243 
    244   CrossCallReturn answer;
    245   DWORD dw = 0xE6578;
    246   CrossCall(client, tag2, dw, &answer);
    247   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    248   EXPECT_EQ(1, actual_params->GetParamsCount());
    249   EXPECT_EQ(tag2, actual_params->GetTag());
    250   ArgType type = INVALID_TYPE;
    251   uint32 param_size = 1;
    252   void* param_addr = actual_params->GetRawParameter(0, &param_size, &type);
    253   ASSERT_EQ(sizeof(dw), param_size);
    254   EXPECT_EQ(ULONG_TYPE, type);
    255   ASSERT_TRUE(NULL != param_addr);
    256   EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
    257 
    258   // Check handling for windows HANDLES.
    259   HANDLE h = HANDLE(0x70000500);
    260   CrossCall(client, tag1, text, h, &answer);
    261   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    262   EXPECT_EQ(2, actual_params->GetParamsCount());
    263   EXPECT_EQ(tag1, actual_params->GetTag());
    264   type = INVALID_TYPE;
    265   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
    266   ASSERT_EQ(sizeof(h), param_size);
    267   EXPECT_EQ(VOIDPTR_TYPE, type);
    268   ASSERT_TRUE(NULL != param_addr);
    269   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
    270 
    271   // Check combination of 32 and 64 bits.
    272   CrossCall(client, tag2, h, dw, h, &answer);
    273   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
    274   EXPECT_EQ(3, actual_params->GetParamsCount());
    275   EXPECT_EQ(tag2, actual_params->GetTag());
    276   type = INVALID_TYPE;
    277   param_addr = actual_params->GetRawParameter(0, &param_size, &type);
    278   ASSERT_EQ(sizeof(h), param_size);
    279   EXPECT_EQ(VOIDPTR_TYPE, type);
    280   ASSERT_TRUE(NULL != param_addr);
    281   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
    282   type = INVALID_TYPE;
    283   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
    284   ASSERT_EQ(sizeof(dw), param_size);
    285   EXPECT_EQ(ULONG_TYPE, type);
    286   ASSERT_TRUE(NULL != param_addr);
    287   EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
    288   type = INVALID_TYPE;
    289   param_addr = actual_params->GetRawParameter(2, &param_size, &type);
    290   ASSERT_EQ(sizeof(h), param_size);
    291   EXPECT_EQ(VOIDPTR_TYPE, type);
    292   ASSERT_TRUE(NULL != param_addr);
    293   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
    294 
    295   CloseChannelEvents(client_control);
    296   delete[] reinterpret_cast<char*>(client_control);
    297 }
    298 
    299 TEST(IPCTest, CrossCallValidation) {
    300   // First a sanity test with a well formed parameter object.
    301   unsigned long value = 124816;
    302   const uint32 kTag = 33;
    303   const uint32 kBufferSize = 256;
    304   ActualCallParams<1, kBufferSize> params_1(kTag);
    305   params_1.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    306   void* buffer = const_cast<void*>(params_1.GetBuffer());
    307 
    308   uint32 out_size = 0;
    309   CrossCallParamsEx* ccp = 0;
    310   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
    311                                             &out_size);
    312   ASSERT_TRUE(NULL != ccp);
    313   EXPECT_TRUE(ccp->GetBuffer() != buffer);
    314   EXPECT_EQ(kTag, ccp->GetTag());
    315   EXPECT_EQ(1, ccp->GetParamsCount());
    316   delete[] (reinterpret_cast<char*>(ccp));
    317 
    318   // Test that we handle integer overflow on the number of params
    319   // correctly. We use a test-only ctor for ActualCallParams that
    320   // allows to create malformed cross-call buffers.
    321   const int32 kPtrDiffSz = sizeof(ptrdiff_t);
    322   for (int32 ix = -1; ix != 3; ++ix) {
    323     uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
    324     ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
    325     params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    326     buffer = const_cast<void*>(params_2.GetBuffer());
    327 
    328     EXPECT_TRUE(NULL != buffer);
    329     ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
    330                                               &out_size);
    331     // If the buffer is malformed the return is NULL.
    332     EXPECT_TRUE(NULL == ccp);
    333   }
    334 
    335   ActualCallParams<1, kBufferSize> params_3(kTag, 1);
    336   params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    337   buffer = const_cast<void*>(params_3.GetBuffer());
    338   EXPECT_TRUE(NULL != buffer);
    339 
    340   uint32 correct_size = params_3.OverrideSize(1);
    341   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    342   EXPECT_TRUE(NULL == ccp);
    343 
    344   // The correct_size is 8 bytes aligned.
    345   params_3.OverrideSize(correct_size - 7);
    346   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    347   EXPECT_TRUE(NULL == ccp);
    348 
    349   params_3.OverrideSize(correct_size);
    350   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    351   EXPECT_TRUE(NULL != ccp);
    352 
    353   // Make sure that two parameters work as expected.
    354   ActualCallParams<2, kBufferSize> params_4(kTag, 2);
    355   params_4.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    356   params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
    357   buffer = const_cast<void*>(params_4.GetBuffer());
    358   EXPECT_TRUE(NULL != buffer);
    359 
    360   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    361   EXPECT_TRUE(NULL != ccp);
    362 
    363 #if defined(_WIN64)
    364   correct_size = params_4.OverrideSize(1);
    365   params_4.OverrideSize(correct_size - 1);
    366   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    367   EXPECT_TRUE(NULL == ccp);
    368 #endif
    369 }
    370 
    371 // This structure is passed to the mock server threads to simulate
    372 // the server side IPC so it has the required kernel objects.
    373 struct ServerEvents {
    374   HANDLE ping;
    375   HANDLE pong;
    376   volatile LONG* state;
    377   HANDLE mutex;
    378 };
    379 
    380 // This is the server thread that quicky answers an IPC and exits.
    381 DWORD WINAPI QuickResponseServer(PVOID param) {
    382   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    383   DWORD wait_result = 0;
    384   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
    385   ::InterlockedExchange(events->state, kAckChannel);
    386   ::SetEvent(events->pong);
    387   return wait_result;
    388 }
    389 
    390 class CrossCallParamsMock : public CrossCallParams {
    391  public:
    392   CrossCallParamsMock(uint32 tag, uint32 params_count)
    393       :  CrossCallParams(tag, params_count) {
    394   }
    395  private:
    396   void* params[4];
    397 };
    398 
    399 void FakeOkAnswerInChannel(void* channel) {
    400   CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
    401   answer->call_outcome = SBOX_ALL_OK;
    402 }
    403 
    404 // Create two threads that will quickly answer IPCs; the first one
    405 // using channel 1 (channel 0 is busy) and one using channel 0. No time-out
    406 // should occur.
    407 TEST(IPCTest, ClientFastServer) {
    408   const size_t channel_size = kIPCChannelSize;
    409   size_t base_start = 0;
    410   IPCControl* client_control =
    411       MakeChannels(channel_size, 4096 * 2, &base_start);
    412   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
    413   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
    414 
    415   char* mem = reinterpret_cast<char*>(client_control);
    416   SharedMemIPCClient client(mem);
    417 
    418   ServerEvents events = {0};
    419   events.ping = client_control->channels[1].ping_event;
    420   events.pong = client_control->channels[1].pong_event;
    421   events.state = &client_control->channels[1].state;
    422 
    423   HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
    424   ASSERT_TRUE(NULL != t1);
    425   ::CloseHandle(t1);
    426 
    427   void* buff0 = client.GetBuffer();
    428   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
    429   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    430   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    431   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    432 
    433   void* buff1 = client.GetBuffer();
    434   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
    435   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    436   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    437   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    438 
    439   EXPECT_EQ(0, client_control->channels[1].ipc_tag);
    440 
    441   uint32 tag = 7654;
    442   CrossCallReturn answer;
    443   CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
    444   FakeOkAnswerInChannel(buff1);
    445 
    446   ResultCode result = client.DoCall(params1, &answer);
    447   if (SBOX_ERROR_CHANNEL_ERROR != result)
    448     client.FreeBuffer(buff1);
    449 
    450   EXPECT_TRUE(SBOX_ALL_OK == result);
    451   EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
    452   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    453   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    454   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    455 
    456   HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
    457   ASSERT_TRUE(NULL != t2);
    458   ::CloseHandle(t2);
    459 
    460   client.FreeBuffer(buff0);
    461   events.ping = client_control->channels[0].ping_event;
    462   events.pong = client_control->channels[0].pong_event;
    463   events.state = &client_control->channels[0].state;
    464 
    465   tag = 4567;
    466   CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
    467   FakeOkAnswerInChannel(buff0);
    468 
    469   result = client.DoCall(params2, &answer);
    470   if (SBOX_ERROR_CHANNEL_ERROR != result)
    471     client.FreeBuffer(buff0);
    472 
    473   EXPECT_TRUE(SBOX_ALL_OK == result);
    474   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
    475   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
    476   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    477   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    478 
    479   CloseChannelEvents(client_control);
    480   ::CloseHandle(client_control->server_alive);
    481 
    482   delete[] reinterpret_cast<char*>(client_control);
    483 }
    484 
    485 // This is the server thread that very slowly answers an IPC and exits. Note
    486 // that the pong event needs to be signaled twice.
    487 DWORD WINAPI SlowResponseServer(PVOID param) {
    488   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    489   DWORD wait_result = 0;
    490   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
    491   ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
    492   ::InterlockedExchange(events->state, kAckChannel);
    493   ::SetEvent(events->pong);
    494   return wait_result;
    495 }
    496 
    497 // This thread's job is to keep the mutex locked.
    498 DWORD WINAPI MainServerThread(PVOID param) {
    499   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    500   DWORD wait_result = 0;
    501   wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
    502   Sleep(kIPCWaitTimeOut1 * 20);
    503   return wait_result;
    504 }
    505 
    506 // Creates a server thread that answers the IPC so slow that is guaranteed to
    507 // trigger the time-out code path in the client. A second thread is created
    508 // to hold locked the server_alive mutex: this signals the client that the
    509 // server is not dead and it retries the wait.
    510 TEST(IPCTest, ClientSlowServer) {
    511   size_t base_start = 0;
    512   IPCControl* client_control =
    513       MakeChannels(kIPCChannelSize, 4096*2, &base_start);
    514   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
    515   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
    516 
    517   char* mem = reinterpret_cast<char*>(client_control);
    518   SharedMemIPCClient client(mem);
    519 
    520   ServerEvents events = {0};
    521   events.ping = client_control->channels[0].ping_event;
    522   events.pong = client_control->channels[0].pong_event;
    523   events.state = &client_control->channels[0].state;
    524 
    525   HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
    526   ASSERT_TRUE(NULL != t1);
    527   ::CloseHandle(t1);
    528 
    529   ServerEvents events2 = {0};
    530   events2.pong = events.pong;
    531   events2.mutex = client_control->server_alive;
    532 
    533   HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
    534   ASSERT_TRUE(NULL != t2);
    535   ::CloseHandle(t2);
    536 
    537   ::Sleep(1);
    538 
    539   void* buff0 = client.GetBuffer();
    540   uint32 tag = 4321;
    541   CrossCallReturn answer;
    542   CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
    543   FakeOkAnswerInChannel(buff0);
    544 
    545   ResultCode result = client.DoCall(params1, &answer);
    546   if (SBOX_ERROR_CHANNEL_ERROR != result)
    547     client.FreeBuffer(buff0);
    548 
    549   EXPECT_TRUE(SBOX_ALL_OK == result);
    550   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
    551   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
    552 
    553   CloseChannelEvents(client_control);
    554   ::CloseHandle(client_control->server_alive);
    555   delete[] reinterpret_cast<char*>(client_control);
    556 }
    557 
    558 // This test-only IPC dispatcher has two handlers with the same signature
    559 // but only CallOneHandler should be used.
    560 class UnitTestIPCDispatcher : public Dispatcher {
    561  public:
    562   enum {
    563     CALL_ONE_TAG = 78,
    564     CALL_TWO_TAG = 87
    565   };
    566 
    567   UnitTestIPCDispatcher();
    568   ~UnitTestIPCDispatcher() {};
    569 
    570   virtual bool SetupService(InterceptionManager* manager, int service) {
    571     return true;
    572   }
    573 
    574  private:
    575   bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
    576     ipc->return_info.extended[0].handle = p1;
    577     ipc->return_info.extended[1].unsigned_int = p2;
    578     return true;
    579   }
    580 
    581   bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
    582     return true;
    583   }
    584 };
    585 
    586 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
    587   static const IPCCall call_one = {
    588     {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE},
    589     reinterpret_cast<CallbackGeneric>(
    590         &UnitTestIPCDispatcher::CallOneHandler)
    591   };
    592   static const IPCCall call_two = {
    593     {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE},
    594     reinterpret_cast<CallbackGeneric>(
    595         &UnitTestIPCDispatcher::CallTwoHandler)
    596   };
    597   ipc_calls_.push_back(call_one);
    598   ipc_calls_.push_back(call_two);
    599 }
    600 
    601 // This test does most of the shared memory IPC client-server roundtrip
    602 // and tests the packing, unpacking and call dispatching.
    603 TEST(IPCTest, SharedMemServerTests) {
    604   size_t base_start = 0;
    605   IPCControl* client_control =
    606       MakeChannels(kIPCChannelSize, 4096, &base_start);
    607   client_control->server_alive = HANDLE(1);
    608   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
    609 
    610   char* mem = reinterpret_cast<char*>(client_control);
    611   SharedMemIPCClient client(mem);
    612 
    613   CrossCallReturn answer;
    614   HANDLE bar = HANDLE(191919);
    615   DWORD foo = 6767676;
    616   CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
    617   void* buff = client.GetBuffer();
    618   ASSERT_TRUE(NULL != buff);
    619 
    620   UnitTestIPCDispatcher dispatcher;
    621   // Since we are directly calling InvokeCallback, most of this structure
    622   // can be set to NULL.
    623   sandbox::SharedMemIPCServer::ServerControl srv_control = {
    624       NULL, NULL, kIPCChannelSize, NULL,
    625       reinterpret_cast<char*>(client_control),
    626       NULL, &dispatcher, {0} };
    627 
    628   sandbox::CrossCallReturn call_return = {0};
    629   EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
    630                                                  &call_return));
    631   EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
    632   EXPECT_TRUE(bar == call_return.extended[0].handle);
    633   EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
    634 
    635   CloseChannelEvents(client_control);
    636   delete[] reinterpret_cast<char*>(client_control);
    637 }
    638 
    639 }  // namespace sandbox
    640