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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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