ipc_unittest.cc 24 KB

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