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   std::wstring 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   std::wstring 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 #if defined(NDEBUG)
    319   // Test hat we handle integer overflow on the number of params
    320   // correctly. We use a test-only ctor for ActualCallParams that
    321   // allows to create malformed cross-call buffers.
    322   const int32 kPtrDiffSz = sizeof(ptrdiff_t);
    323   for (int32 ix = -1; ix != 3; ++ix) {
    324     uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
    325     ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
    326     params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    327     buffer = const_cast<void*>(params_2.GetBuffer());
    328 
    329     EXPECT_TRUE(NULL != buffer);
    330     ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
    331                                               &out_size);
    332     // If the buffer is malformed the return is NULL.
    333     EXPECT_TRUE(NULL == ccp);
    334   }
    335 #endif  // defined(NDEBUG)
    336 
    337   ActualCallParams<1, kBufferSize> params_3(kTag, 1);
    338   params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    339   buffer = const_cast<void*>(params_3.GetBuffer());
    340   EXPECT_TRUE(NULL != buffer);
    341 
    342   uint32 correct_size = params_3.OverrideSize(1);
    343   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    344   EXPECT_TRUE(NULL == ccp);
    345 
    346   // The correct_size is 8 bytes aligned.
    347   params_3.OverrideSize(correct_size - 7);
    348   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    349   EXPECT_TRUE(NULL == ccp);
    350 
    351   params_3.OverrideSize(correct_size);
    352   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    353   EXPECT_TRUE(NULL != ccp);
    354 
    355   // Make sure that two parameters work as expected.
    356   ActualCallParams<2, kBufferSize> params_4(kTag, 2);
    357   params_4.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
    358   params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
    359   buffer = const_cast<void*>(params_4.GetBuffer());
    360   EXPECT_TRUE(NULL != buffer);
    361 
    362   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    363   EXPECT_TRUE(NULL != ccp);
    364 
    365 #if defined(_WIN64)
    366   correct_size = params_4.OverrideSize(1);
    367   params_4.OverrideSize(correct_size - 1);
    368   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
    369   EXPECT_TRUE(NULL == ccp);
    370 #endif
    371 }
    372 
    373 // This structure is passed to the mock server threads to simulate
    374 // the server side IPC so it has the required kernel objects.
    375 struct ServerEvents {
    376   HANDLE ping;
    377   HANDLE pong;
    378   volatile LONG* state;
    379   HANDLE mutex;
    380 };
    381 
    382 // This is the server thread that quicky answers an IPC and exits.
    383 DWORD WINAPI QuickResponseServer(PVOID param) {
    384   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    385   DWORD wait_result = 0;
    386   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
    387   ::InterlockedExchange(events->state, kAckChannel);
    388   ::SetEvent(events->pong);
    389   return wait_result;
    390 }
    391 
    392 class CrossCallParamsMock : public CrossCallParams {
    393  public:
    394   CrossCallParamsMock(uint32 tag, uint32 params_count)
    395       :  CrossCallParams(tag, params_count) {
    396   }
    397  private:
    398   void* params[4];
    399 };
    400 
    401 void FakeOkAnswerInChannel(void* channel) {
    402   CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
    403   answer->call_outcome = SBOX_ALL_OK;
    404 }
    405 
    406 // Create two threads that will quickly answer IPCs; the first one
    407 // using channel 1 (channel 0 is busy) and one using channel 0. No time-out
    408 // should occur.
    409 TEST(IPCTest, ClientFastServer) {
    410   const size_t channel_size = kIPCChannelSize;
    411   size_t base_start = 0;
    412   IPCControl* client_control =
    413       MakeChannels(channel_size, 4096 * 2, &base_start);
    414   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
    415   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
    416 
    417   char* mem = reinterpret_cast<char*>(client_control);
    418   SharedMemIPCClient client(mem);
    419 
    420   ServerEvents events = {0};
    421   events.ping = client_control->channels[1].ping_event;
    422   events.pong = client_control->channels[1].pong_event;
    423   events.state = &client_control->channels[1].state;
    424 
    425   HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
    426   ASSERT_TRUE(NULL != t1);
    427   ::CloseHandle(t1);
    428 
    429   void* buff0 = client.GetBuffer();
    430   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
    431   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    432   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    433   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    434 
    435   void* buff1 = client.GetBuffer();
    436   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
    437   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    438   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
    439   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    440 
    441   EXPECT_EQ(0, client_control->channels[1].ipc_tag);
    442 
    443   uint32 tag = 7654;
    444   CrossCallReturn answer;
    445   CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
    446   FakeOkAnswerInChannel(buff1);
    447 
    448   ResultCode result = client.DoCall(params1, &answer);
    449   if (SBOX_ERROR_CHANNEL_ERROR != result)
    450     client.FreeBuffer(buff1);
    451 
    452   EXPECT_TRUE(SBOX_ALL_OK == result);
    453   EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
    454   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
    455   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    456   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    457 
    458   HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
    459   ASSERT_TRUE(NULL != t2);
    460   ::CloseHandle(t2);
    461 
    462   client.FreeBuffer(buff0);
    463   events.ping = client_control->channels[0].ping_event;
    464   events.pong = client_control->channels[0].pong_event;
    465   events.state = &client_control->channels[0].state;
    466 
    467   tag = 4567;
    468   CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
    469   FakeOkAnswerInChannel(buff0);
    470 
    471   result = client.DoCall(params2, &answer);
    472   if (SBOX_ERROR_CHANNEL_ERROR != result)
    473     client.FreeBuffer(buff0);
    474 
    475   EXPECT_TRUE(SBOX_ALL_OK == result);
    476   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
    477   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
    478   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
    479   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
    480 
    481   CloseChannelEvents(client_control);
    482   ::CloseHandle(client_control->server_alive);
    483 
    484   delete[] reinterpret_cast<char*>(client_control);
    485 }
    486 
    487 // This is the server thread that very slowly answers an IPC and exits. Note
    488 // that the pong event needs to be signaled twice.
    489 DWORD WINAPI SlowResponseServer(PVOID param) {
    490   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    491   DWORD wait_result = 0;
    492   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
    493   ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
    494   ::InterlockedExchange(events->state, kAckChannel);
    495   ::SetEvent(events->pong);
    496   return wait_result;
    497 }
    498 
    499 // This thread's job is to keep the mutex locked.
    500 DWORD WINAPI MainServerThread(PVOID param) {
    501   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
    502   DWORD wait_result = 0;
    503   wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
    504   Sleep(kIPCWaitTimeOut1 * 20);
    505   return wait_result;
    506 }
    507 
    508 // Creates a server thread that answers the IPC so slow that is guaranteed to
    509 // trigger the time-out code path in the client. A second thread is created
    510 // to hold locked the server_alive mutex: this signals the client that the
    511 // server is not dead and it retries the wait.
    512 TEST(IPCTest, ClientSlowServer) {
    513   size_t base_start = 0;
    514   IPCControl* client_control =
    515       MakeChannels(kIPCChannelSize, 4096*2, &base_start);
    516   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
    517   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
    518 
    519   char* mem = reinterpret_cast<char*>(client_control);
    520   SharedMemIPCClient client(mem);
    521 
    522   ServerEvents events = {0};
    523   events.ping = client_control->channels[0].ping_event;
    524   events.pong = client_control->channels[0].pong_event;
    525   events.state = &client_control->channels[0].state;
    526 
    527   HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
    528   ASSERT_TRUE(NULL != t1);
    529   ::CloseHandle(t1);
    530 
    531   ServerEvents events2 = {0};
    532   events2.pong = events.pong;
    533   events2.mutex = client_control->server_alive;
    534 
    535   HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
    536   ASSERT_TRUE(NULL != t2);
    537   ::CloseHandle(t2);
    538 
    539   ::Sleep(1);
    540 
    541   void* buff0 = client.GetBuffer();
    542   uint32 tag = 4321;
    543   CrossCallReturn answer;
    544   CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
    545   FakeOkAnswerInChannel(buff0);
    546 
    547   ResultCode result = client.DoCall(params1, &answer);
    548   if (SBOX_ERROR_CHANNEL_ERROR != result)
    549     client.FreeBuffer(buff0);
    550 
    551   EXPECT_TRUE(SBOX_ALL_OK == result);
    552   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
    553   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
    554 
    555   CloseChannelEvents(client_control);
    556   ::CloseHandle(client_control->server_alive);
    557   delete[] reinterpret_cast<char*>(client_control);
    558 }
    559 
    560 // This test-only IPC dispatcher has two handlers with the same signature
    561 // but only CallOneHandler should be used.
    562 class UnitTestIPCDispatcher : public Dispatcher {
    563  public:
    564   enum {
    565     CALL_ONE_TAG = 78,
    566     CALL_TWO_TAG = 87
    567   };
    568 
    569   UnitTestIPCDispatcher();
    570   ~UnitTestIPCDispatcher() {};
    571 
    572   virtual bool SetupService(InterceptionManager* manager, int service) {
    573     return true;
    574   }
    575 
    576  private:
    577   bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
    578     ipc->return_info.extended[0].handle = p1;
    579     ipc->return_info.extended[1].unsigned_int = p2;
    580     return true;
    581   }
    582 
    583   bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
    584     return true;
    585   }
    586 };
    587 
    588 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
    589   static const IPCCall call_one = {
    590     {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE},
    591     reinterpret_cast<CallbackGeneric>(
    592         &UnitTestIPCDispatcher::CallOneHandler)
    593   };
    594   static const IPCCall call_two = {
    595     {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE},
    596     reinterpret_cast<CallbackGeneric>(
    597         &UnitTestIPCDispatcher::CallTwoHandler)
    598   };
    599   ipc_calls_.push_back(call_one);
    600   ipc_calls_.push_back(call_two);
    601 }
    602 
    603 // This test does most of the shared memory IPC client-server roundtrip
    604 // and tests the packing, unpacking and call dispatching.
    605 TEST(IPCTest, SharedMemServerTests) {
    606   size_t base_start = 0;
    607   IPCControl* client_control =
    608       MakeChannels(kIPCChannelSize, 4096, &base_start);
    609   client_control->server_alive = HANDLE(1);
    610   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
    611 
    612   char* mem = reinterpret_cast<char*>(client_control);
    613   SharedMemIPCClient client(mem);
    614 
    615   CrossCallReturn answer;
    616   HANDLE bar = HANDLE(191919);
    617   DWORD foo = 6767676;
    618   CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
    619   void* buff = client.GetBuffer();
    620   ASSERT_TRUE(NULL != buff);
    621 
    622   UnitTestIPCDispatcher dispatcher;
    623   // Since we are directly calling InvokeCallback, most of this structure
    624   // can be set to NULL.
    625   sandbox::SharedMemIPCServer::ServerControl srv_control = {
    626       NULL, NULL, kIPCChannelSize, NULL,
    627       reinterpret_cast<char*>(client_control),
    628       NULL, &dispatcher, {0} };
    629 
    630   sandbox::CrossCallReturn call_return = {0};
    631   EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
    632                                                  &call_return));
    633   EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
    634   EXPECT_TRUE(bar == call_return.extended[0].handle);
    635   EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
    636 
    637   CloseChannelEvents(client_control);
    638   delete[] reinterpret_cast<char*>(client_control);
    639 }
    640 
    641 }  // namespace sandbox
    642