sharedmem_ipc_server.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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 "sandbox/win/src/sharedmem_ipc_server.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "base/callback.h"
  8. #include "base/check.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/notreached.h"
  11. #include "sandbox/win/src/crosscall_params.h"
  12. #include "sandbox/win/src/crosscall_server.h"
  13. #include "sandbox/win/src/ipc_args.h"
  14. #include "sandbox/win/src/sandbox.h"
  15. #include "sandbox/win/src/sandbox_types.h"
  16. #include "sandbox/win/src/sharedmem_ipc_client.h"
  17. #include "sandbox/win/src/threadpool.h"
  18. namespace {
  19. // This handle must not be closed.
  20. volatile HANDLE g_alive_mutex = nullptr;
  21. } // namespace
  22. namespace sandbox {
  23. SharedMemIPCServer::ServerControl::ServerControl() {}
  24. SharedMemIPCServer::ServerControl::~ServerControl() {}
  25. SharedMemIPCServer::SharedMemIPCServer(HANDLE target_process,
  26. DWORD target_process_id,
  27. ThreadPool* thread_pool,
  28. Dispatcher* dispatcher)
  29. : client_control_(nullptr),
  30. thread_pool_(thread_pool),
  31. target_process_(target_process),
  32. target_process_id_(target_process_id),
  33. call_dispatcher_(dispatcher) {
  34. // We create a initially owned mutex. If the server dies unexpectedly,
  35. // the thread that owns it will fail to release the lock and windows will
  36. // report to the target (when it tries to acquire it) that the wait was
  37. // abandoned. Note: We purposely leak the local handle because we want it to
  38. // be closed by Windows itself so it is properly marked as abandoned if the
  39. // server dies.
  40. if (!g_alive_mutex) {
  41. HANDLE mutex = ::CreateMutexW(nullptr, true, nullptr);
  42. if (::InterlockedCompareExchangePointer(&g_alive_mutex, mutex, nullptr)) {
  43. // We lost the race to create the mutex.
  44. ::CloseHandle(mutex);
  45. }
  46. }
  47. }
  48. SharedMemIPCServer::~SharedMemIPCServer() {
  49. // Free the wait handles associated with the thread pool.
  50. if (!thread_pool_->UnRegisterWaits(this)) {
  51. // Better to leak than to crash.
  52. return;
  53. }
  54. server_contexts_.clear();
  55. if (client_control_)
  56. ::UnmapViewOfFile(client_control_);
  57. }
  58. bool SharedMemIPCServer::Init(void* shared_mem,
  59. uint32_t shared_size,
  60. uint32_t channel_size) {
  61. // The shared memory needs to be at least as big as a channel.
  62. if (shared_size < channel_size) {
  63. return false;
  64. }
  65. // The channel size should be aligned.
  66. if (0 != (channel_size % 32)) {
  67. return false;
  68. }
  69. // Calculate how many channels we can fit in the shared memory.
  70. shared_size -= offsetof(IPCControl, channels);
  71. size_t channel_count = shared_size / (sizeof(ChannelControl) + channel_size);
  72. // If we cannot fit even one channel we bail out.
  73. if (0 == channel_count) {
  74. return false;
  75. }
  76. // Calculate the start of the first channel.
  77. size_t base_start =
  78. (sizeof(ChannelControl) * channel_count) + offsetof(IPCControl, channels);
  79. client_control_ = reinterpret_cast<IPCControl*>(shared_mem);
  80. client_control_->channels_count = 0;
  81. // This is the initialization that we do per-channel. Basically:
  82. // 1) make two events (ping & pong)
  83. // 2) create handles to the events for the client and the server.
  84. // 3) initialize the channel (client_context) with the state.
  85. // 4) initialize the server side of the channel (service_context).
  86. // 5) call the thread provider RegisterWait to register the ping events.
  87. for (size_t ix = 0; ix != channel_count; ++ix) {
  88. ChannelControl* client_context = &client_control_->channels[ix];
  89. ServerControl* service_context = new ServerControl;
  90. server_contexts_.push_back(base::WrapUnique(service_context));
  91. if (!MakeEvents(&service_context->ping_event, &service_context->pong_event,
  92. &client_context->ping_event, &client_context->pong_event)) {
  93. return false;
  94. }
  95. client_context->channel_base = base_start;
  96. client_context->state = kFreeChannel;
  97. // Note that some of these values are available as members of this object
  98. // but we put them again into the service_context because we will be called
  99. // on a static method (ThreadPingEventReady). In particular, target_process_
  100. // is a raw handle that is not owned by this object (it's owned by the
  101. // owner of this object), and we are storing it in multiple places.
  102. service_context->shared_base = reinterpret_cast<char*>(shared_mem);
  103. service_context->channel_size = channel_size;
  104. service_context->channel = client_context;
  105. service_context->channel_buffer =
  106. service_context->shared_base + client_context->channel_base;
  107. service_context->dispatcher = call_dispatcher_;
  108. service_context->target_info.process = target_process_;
  109. service_context->target_info.process_id = target_process_id_;
  110. // Advance to the next channel.
  111. base_start += channel_size;
  112. // Register the ping event with the threadpool.
  113. thread_pool_->RegisterWait(this, service_context->ping_event.Get(),
  114. ThreadPingEventReady, service_context);
  115. }
  116. if (!::DuplicateHandle(::GetCurrentProcess(), g_alive_mutex, target_process_,
  117. &client_control_->server_alive,
  118. SYNCHRONIZE | EVENT_MODIFY_STATE, false, 0)) {
  119. return false;
  120. }
  121. // This last setting indicates to the client all is setup.
  122. client_control_->channels_count = channel_count;
  123. return true;
  124. }
  125. bool SharedMemIPCServer::InvokeCallback(const ServerControl* service_context,
  126. void* ipc_buffer,
  127. CrossCallReturn* call_result) {
  128. // Set the default error code;
  129. SetCallError(SBOX_ERROR_INVALID_IPC, call_result);
  130. uint32_t output_size = 0;
  131. // Parse, verify and copy the message. The handler operates on a copy
  132. // of the message so the client cannot play dirty tricks by changing the
  133. // data in the channel while the IPC is being processed.
  134. std::unique_ptr<CrossCallParamsEx> params(CrossCallParamsEx::CreateFromBuffer(
  135. ipc_buffer, service_context->channel_size, &output_size));
  136. if (!params.get())
  137. return false;
  138. IpcTag tag = params->GetTag();
  139. static_assert(0 == INVALID_TYPE, "incorrect type enum");
  140. IPCParams ipc_params = {tag};
  141. void* args[kMaxIpcParams];
  142. if (!GetArgs(params.get(), &ipc_params, args))
  143. return false;
  144. IPCInfo ipc_info = {tag};
  145. ipc_info.client_info = &service_context->target_info;
  146. Dispatcher* dispatcher = service_context->dispatcher;
  147. DCHECK(dispatcher);
  148. bool error = true;
  149. Dispatcher* handler = nullptr;
  150. Dispatcher::CallbackGeneric callback_generic;
  151. handler = dispatcher->OnMessageReady(&ipc_params, &callback_generic);
  152. if (handler) {
  153. switch (params->GetParamsCount()) {
  154. case 0: {
  155. // Ask the IPC dispatcher if it can service this IPC.
  156. Dispatcher::Callback0 callback =
  157. reinterpret_cast<Dispatcher::Callback0>(callback_generic);
  158. if (!(handler->*callback)(&ipc_info))
  159. break;
  160. error = false;
  161. break;
  162. }
  163. case 1: {
  164. Dispatcher::Callback1 callback =
  165. reinterpret_cast<Dispatcher::Callback1>(callback_generic);
  166. if (!(handler->*callback)(&ipc_info, args[0]))
  167. break;
  168. error = false;
  169. break;
  170. }
  171. case 2: {
  172. Dispatcher::Callback2 callback =
  173. reinterpret_cast<Dispatcher::Callback2>(callback_generic);
  174. if (!(handler->*callback)(&ipc_info, args[0], args[1]))
  175. break;
  176. error = false;
  177. break;
  178. }
  179. case 3: {
  180. Dispatcher::Callback3 callback =
  181. reinterpret_cast<Dispatcher::Callback3>(callback_generic);
  182. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2]))
  183. break;
  184. error = false;
  185. break;
  186. }
  187. case 4: {
  188. Dispatcher::Callback4 callback =
  189. reinterpret_cast<Dispatcher::Callback4>(callback_generic);
  190. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2],
  191. args[3]))
  192. break;
  193. error = false;
  194. break;
  195. }
  196. case 5: {
  197. Dispatcher::Callback5 callback =
  198. reinterpret_cast<Dispatcher::Callback5>(callback_generic);
  199. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
  200. args[4]))
  201. break;
  202. error = false;
  203. break;
  204. }
  205. case 6: {
  206. Dispatcher::Callback6 callback =
  207. reinterpret_cast<Dispatcher::Callback6>(callback_generic);
  208. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
  209. args[4], args[5]))
  210. break;
  211. error = false;
  212. break;
  213. }
  214. case 7: {
  215. Dispatcher::Callback7 callback =
  216. reinterpret_cast<Dispatcher::Callback7>(callback_generic);
  217. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
  218. args[4], args[5], args[6]))
  219. break;
  220. error = false;
  221. break;
  222. }
  223. case 8: {
  224. Dispatcher::Callback8 callback =
  225. reinterpret_cast<Dispatcher::Callback8>(callback_generic);
  226. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
  227. args[4], args[5], args[6], args[7]))
  228. break;
  229. error = false;
  230. break;
  231. }
  232. case 9: {
  233. Dispatcher::Callback9 callback =
  234. reinterpret_cast<Dispatcher::Callback9>(callback_generic);
  235. if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3],
  236. args[4], args[5], args[6], args[7], args[8]))
  237. break;
  238. error = false;
  239. break;
  240. }
  241. default: {
  242. NOTREACHED();
  243. break;
  244. }
  245. }
  246. }
  247. if (error) {
  248. if (handler)
  249. SetCallError(SBOX_ERROR_FAILED_IPC, call_result);
  250. } else {
  251. memcpy(call_result, &ipc_info.return_info, sizeof(*call_result));
  252. SetCallSuccess(call_result);
  253. if (params->IsInOut()) {
  254. // Maybe the params got changed by the broker. We need to upadte the
  255. // memory section.
  256. memcpy(ipc_buffer, params.get(), output_size);
  257. }
  258. }
  259. ReleaseArgs(&ipc_params, args);
  260. return !error;
  261. }
  262. // This function gets called by a thread from the thread pool when a
  263. // ping event fires. The context is the same as passed in the RegisterWait()
  264. // call above.
  265. void __stdcall SharedMemIPCServer::ThreadPingEventReady(void* context,
  266. unsigned char) {
  267. if (!context) {
  268. DCHECK(false);
  269. return;
  270. }
  271. ServerControl* service_context = reinterpret_cast<ServerControl*>(context);
  272. // Since the event fired, the channel *must* be busy. Change to kAckChannel
  273. // while we service it.
  274. LONG last_state = ::InterlockedCompareExchange(
  275. &service_context->channel->state, kAckChannel, kBusyChannel);
  276. if (kBusyChannel != last_state) {
  277. DCHECK(false);
  278. return;
  279. }
  280. // Prepare the result structure. At this point we will return some result
  281. // even if the IPC is invalid, malformed or has no handler.
  282. CrossCallReturn call_result = {0};
  283. void* buffer = service_context->channel_buffer;
  284. InvokeCallback(service_context, buffer, &call_result);
  285. // Copy the answer back into the channel and signal the pong event. This
  286. // should wake up the client so it can finish the ipc cycle.
  287. CrossCallParams* call_params = reinterpret_cast<CrossCallParams*>(buffer);
  288. memcpy(call_params->GetCallReturn(), &call_result, sizeof(call_result));
  289. ::InterlockedExchange(&service_context->channel->state, kAckChannel);
  290. ::SetEvent(service_context->pong_event.Get());
  291. }
  292. bool SharedMemIPCServer::MakeEvents(base::win::ScopedHandle* server_ping,
  293. base::win::ScopedHandle* server_pong,
  294. HANDLE* client_ping,
  295. HANDLE* client_pong) {
  296. // Note that the IPC client has no right to delete the events. That would
  297. // cause problems. The server *owns* the events.
  298. const DWORD kDesiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE;
  299. // The events are auto reset, and start not signaled.
  300. server_ping->Set(::CreateEventW(nullptr, false, false, nullptr));
  301. if (!::DuplicateHandle(::GetCurrentProcess(), server_ping->Get(),
  302. target_process_, client_ping, kDesiredAccess, false,
  303. 0)) {
  304. return false;
  305. }
  306. server_pong->Set(::CreateEventW(nullptr, false, false, nullptr));
  307. if (!::DuplicateHandle(::GetCurrentProcess(), server_pong->Get(),
  308. target_process_, client_pong, kDesiredAccess, false,
  309. 0)) {
  310. return false;
  311. }
  312. return true;
  313. }
  314. } // namespace sandbox