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
12namespace sandbox {
13
14// Helper function to make the fake shared memory with some
15// basic elements initialized.
16IPCControl* 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
34enum TestFixMode {
35  FIX_NO_EVENTS,
36  FIX_PONG_READY,
37  FIX_PONG_NOT_READY
38};
39
40void 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
55void 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
63TEST(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
79TEST(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
147TEST(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
228TEST(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
299TEST(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.
375struct 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.
383DWORD 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
392class 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
401void 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.
409TEST(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.
489DWORD 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.
500DWORD 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.
512TEST(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.
562class 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
588UnitTestIPCDispatcher::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.
605TEST(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