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/callback.h" 6 #include "base/logging.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "sandbox/win/src/sharedmem_ipc_server.h" 9 #include "sandbox/win/src/sharedmem_ipc_client.h" 10 #include "sandbox/win/src/sandbox.h" 11 #include "sandbox/win/src/sandbox_types.h" 12 #include "sandbox/win/src/crosscall_params.h" 13 #include "sandbox/win/src/crosscall_server.h" 14 15 namespace { 16 // This handle must not be closed. 17 volatile HANDLE g_alive_mutex = NULL; 18 } 19 20 namespace sandbox { 21 22 SharedMemIPCServer::SharedMemIPCServer(HANDLE target_process, 23 DWORD target_process_id, 24 HANDLE target_job, 25 ThreadProvider* thread_provider, 26 Dispatcher* dispatcher) 27 : client_control_(NULL), 28 thread_provider_(thread_provider), 29 target_process_(target_process), 30 target_process_id_(target_process_id), 31 target_job_object_(target_job), 32 call_dispatcher_(dispatcher) { 33 // We create a initially owned mutex. If the server dies unexpectedly, 34 // the thread that owns it will fail to release the lock and windows will 35 // report to the target (when it tries to acquire it) that the wait was 36 // abandoned. Note: We purposely leak the local handle because we want it to 37 // be closed by Windows itself so it is properly marked as abandoned if the 38 // server dies. 39 if (!g_alive_mutex) { 40 HANDLE mutex = ::CreateMutexW(NULL, TRUE, NULL); 41 if (::InterlockedCompareExchangePointer(&g_alive_mutex, mutex, NULL)) { 42 // We lost the race to create the mutex. 43 ::CloseHandle(mutex); 44 } 45 } 46 } 47 48 SharedMemIPCServer::~SharedMemIPCServer() { 49 // Free the wait handles associated with the thread pool. 50 if (!thread_provider_->UnRegisterWaits(this)) { 51 // Better to leak than to crash. 52 return; 53 } 54 // Free the IPC signal events. 55 ServerContexts::iterator it; 56 for (it = server_contexts_.begin(); it != server_contexts_.end(); ++it) { 57 ServerControl* context = (*it); 58 ::CloseHandle(context->ping_event); 59 ::CloseHandle(context->pong_event); 60 delete context; 61 } 62 } 63 64 bool SharedMemIPCServer::Init(void* shared_mem, uint32 shared_size, 65 uint32 channel_size) { 66 // The shared memory needs to be at least as big as a channel. 67 if (shared_size < channel_size) { 68 return false; 69 } 70 // The channel size should be aligned. 71 if (0 != (channel_size % 32)) { 72 return false; 73 } 74 75 // Calculate how many channels we can fit in the shared memory. 76 shared_size -= offsetof(IPCControl, channels); 77 size_t channel_count = shared_size / (sizeof(ChannelControl) + channel_size); 78 79 // If we cannot fit even one channel we bail out. 80 if (0 == channel_count) { 81 return false; 82 } 83 // Calculate the start of the first channel. 84 size_t base_start = (sizeof(ChannelControl)* channel_count) + 85 offsetof(IPCControl, channels); 86 87 client_control_ = reinterpret_cast<IPCControl*>(shared_mem); 88 client_control_->channels_count = 0; 89 90 // This is the initialization that we do per-channel. Basically: 91 // 1) make two events (ping & pong) 92 // 2) create handles to the events for the client and the server. 93 // 3) initialize the channel (client_context) with the state. 94 // 4) initialize the server side of the channel (service_context). 95 // 5) call the thread provider RegisterWait to register the ping events. 96 for (size_t ix = 0; ix != channel_count; ++ix) { 97 ChannelControl* client_context = &client_control_->channels[ix]; 98 ServerControl* service_context = new ServerControl; 99 server_contexts_.push_back(service_context); 100 101 if (!MakeEvents(&service_context->ping_event, 102 &service_context->pong_event, 103 &client_context->ping_event, 104 &client_context->pong_event)) { 105 return false; 106 } 107 108 client_context->channel_base = base_start; 109 client_context->state = kFreeChannel; 110 111 // Note that some of these values are available as members of this 112 // object but we put them again into the service_context because we 113 // will be called on a static method (ThreadPingEventReady) 114 service_context->shared_base = reinterpret_cast<char*>(shared_mem); 115 service_context->channel_size = channel_size; 116 service_context->channel = client_context; 117 service_context->channel_buffer = service_context->shared_base + 118 client_context->channel_base; 119 service_context->dispatcher = call_dispatcher_; 120 service_context->target_info.process = target_process_; 121 service_context->target_info.process_id = target_process_id_; 122 service_context->target_info.job_object = target_job_object_; 123 // Advance to the next channel. 124 base_start += channel_size; 125 // Register the ping event with the threadpool. 126 thread_provider_->RegisterWait(this, service_context->ping_event, 127 ThreadPingEventReady, service_context); 128 } 129 if (!::DuplicateHandle(::GetCurrentProcess(), g_alive_mutex, 130 target_process_, &client_control_->server_alive, 131 SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, 0)) { 132 return false; 133 } 134 // This last setting indicates to the client all is setup. 135 client_control_->channels_count = channel_count; 136 return true; 137 } 138 139 // Releases memory allocated for IPC arguments, if needed. 140 void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) { 141 for (size_t i = 0; i < kMaxIpcParams; i++) { 142 switch (ipc_params->args[i]) { 143 case WCHAR_TYPE: { 144 delete reinterpret_cast<base::string16*>(args[i]); 145 args[i] = NULL; 146 break; 147 } 148 case INOUTPTR_TYPE: { 149 delete reinterpret_cast<CountedBuffer*>(args[i]); 150 args[i] = NULL; 151 break; 152 } 153 default: break; 154 } 155 } 156 } 157 158 // Fills up the list of arguments (args and ipc_params) for an IPC call. 159 bool GetArgs(CrossCallParamsEx* params, IPCParams* ipc_params, 160 void* args[kMaxIpcParams]) { 161 if (kMaxIpcParams < params->GetParamsCount()) 162 return false; 163 164 for (uint32 i = 0; i < params->GetParamsCount(); i++) { 165 uint32 size; 166 ArgType type; 167 args[i] = params->GetRawParameter(i, &size, &type); 168 if (args[i]) { 169 ipc_params->args[i] = type; 170 switch (type) { 171 case WCHAR_TYPE: { 172 scoped_ptr<base::string16> data(new base::string16); 173 if (!params->GetParameterStr(i, data.get())) { 174 args[i] = 0; 175 ReleaseArgs(ipc_params, args); 176 return false; 177 } 178 args[i] = data.release(); 179 break; 180 } 181 case ULONG_TYPE: { 182 uint32 data; 183 if (!params->GetParameter32(i, &data)) { 184 ReleaseArgs(ipc_params, args); 185 return false; 186 } 187 IPCInt ipc_int(data); 188 args[i] = ipc_int.AsVoidPtr(); 189 break; 190 } 191 case VOIDPTR_TYPE : { 192 void* data; 193 if (!params->GetParameterVoidPtr(i, &data)) { 194 ReleaseArgs(ipc_params, args); 195 return false; 196 } 197 args[i] = data; 198 break; 199 } 200 case INOUTPTR_TYPE: { 201 if (!args[i]) { 202 ReleaseArgs(ipc_params, args); 203 return false; 204 } 205 CountedBuffer* buffer = new CountedBuffer(args[i] , size); 206 args[i] = buffer; 207 break; 208 } 209 default: break; 210 } 211 } 212 } 213 return true; 214 } 215 216 bool SharedMemIPCServer::InvokeCallback(const ServerControl* service_context, 217 void* ipc_buffer, 218 CrossCallReturn* call_result) { 219 // Set the default error code; 220 SetCallError(SBOX_ERROR_INVALID_IPC, call_result); 221 uint32 output_size = 0; 222 // Parse, verify and copy the message. The handler operates on a copy 223 // of the message so the client cannot play dirty tricks by changing the 224 // data in the channel while the IPC is being processed. 225 scoped_ptr<CrossCallParamsEx> params( 226 CrossCallParamsEx::CreateFromBuffer(ipc_buffer, 227 service_context->channel_size, 228 &output_size)); 229 if (!params.get()) 230 return false; 231 232 uint32 tag = params->GetTag(); 233 COMPILE_ASSERT(0 == INVALID_TYPE, Incorrect_type_enum); 234 IPCParams ipc_params = {0}; 235 ipc_params.ipc_tag = tag; 236 237 void* args[kMaxIpcParams]; 238 if (!GetArgs(params.get(), &ipc_params, args)) 239 return false; 240 241 IPCInfo ipc_info = {0}; 242 ipc_info.ipc_tag = tag; 243 ipc_info.client_info = &service_context->target_info; 244 Dispatcher* dispatcher = service_context->dispatcher; 245 DCHECK(dispatcher); 246 bool error = true; 247 Dispatcher* handler = NULL; 248 249 Dispatcher::CallbackGeneric callback_generic; 250 handler = dispatcher->OnMessageReady(&ipc_params, &callback_generic); 251 if (handler) { 252 switch (params->GetParamsCount()) { 253 case 0: { 254 // Ask the IPC dispatcher if she can service this IPC. 255 Dispatcher::Callback0 callback = 256 reinterpret_cast<Dispatcher::Callback0>(callback_generic); 257 if (!(handler->*callback)(&ipc_info)) 258 break; 259 error = false; 260 break; 261 } 262 case 1: { 263 Dispatcher::Callback1 callback = 264 reinterpret_cast<Dispatcher::Callback1>(callback_generic); 265 if (!(handler->*callback)(&ipc_info, args[0])) 266 break; 267 error = false; 268 break; 269 } 270 case 2: { 271 Dispatcher::Callback2 callback = 272 reinterpret_cast<Dispatcher::Callback2>(callback_generic); 273 if (!(handler->*callback)(&ipc_info, args[0], args[1])) 274 break; 275 error = false; 276 break; 277 } 278 case 3: { 279 Dispatcher::Callback3 callback = 280 reinterpret_cast<Dispatcher::Callback3>(callback_generic); 281 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2])) 282 break; 283 error = false; 284 break; 285 } 286 case 4: { 287 Dispatcher::Callback4 callback = 288 reinterpret_cast<Dispatcher::Callback4>(callback_generic); 289 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], 290 args[3])) 291 break; 292 error = false; 293 break; 294 } 295 case 5: { 296 Dispatcher::Callback5 callback = 297 reinterpret_cast<Dispatcher::Callback5>(callback_generic); 298 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], 299 args[4])) 300 break; 301 error = false; 302 break; 303 } 304 case 6: { 305 Dispatcher::Callback6 callback = 306 reinterpret_cast<Dispatcher::Callback6>(callback_generic); 307 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], 308 args[4], args[5])) 309 break; 310 error = false; 311 break; 312 } 313 case 7: { 314 Dispatcher::Callback7 callback = 315 reinterpret_cast<Dispatcher::Callback7>(callback_generic); 316 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], 317 args[4], args[5], args[6])) 318 break; 319 error = false; 320 break; 321 } 322 case 8: { 323 Dispatcher::Callback8 callback = 324 reinterpret_cast<Dispatcher::Callback8>(callback_generic); 325 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], 326 args[4], args[5], args[6], args[7])) 327 break; 328 error = false; 329 break; 330 } 331 case 9: { 332 Dispatcher::Callback9 callback = 333 reinterpret_cast<Dispatcher::Callback9>(callback_generic); 334 if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], 335 args[4], args[5], args[6], args[7], args[8])) 336 break; 337 error = false; 338 break; 339 } 340 default: { 341 NOTREACHED(); 342 break; 343 } 344 } 345 } 346 347 if (error) { 348 if (handler) 349 SetCallError(SBOX_ERROR_FAILED_IPC, call_result); 350 } else { 351 memcpy(call_result, &ipc_info.return_info, sizeof(*call_result)); 352 SetCallSuccess(call_result); 353 if (params->IsInOut()) { 354 // Maybe the params got changed by the broker. We need to upadte the 355 // memory section. 356 memcpy(ipc_buffer, params.get(), output_size); 357 } 358 } 359 360 ReleaseArgs(&ipc_params, args); 361 362 return !error; 363 } 364 365 // This function gets called by a thread from the thread pool when a 366 // ping event fires. The context is the same as passed in the RegisterWait() 367 // call above. 368 void __stdcall SharedMemIPCServer::ThreadPingEventReady(void* context, 369 unsigned char) { 370 if (NULL == context) { 371 DCHECK(false); 372 return; 373 } 374 ServerControl* service_context = reinterpret_cast<ServerControl*>(context); 375 // Since the event fired, the channel *must* be busy. Change to kAckChannel 376 // while we service it. 377 LONG last_state = 378 ::InterlockedCompareExchange(&service_context->channel->state, 379 kAckChannel, kBusyChannel); 380 if (kBusyChannel != last_state) { 381 DCHECK(false); 382 return; 383 } 384 385 // Prepare the result structure. At this point we will return some result 386 // even if the IPC is invalid, malformed or has no handler. 387 CrossCallReturn call_result = {0}; 388 void* buffer = service_context->channel_buffer; 389 390 InvokeCallback(service_context, buffer, &call_result); 391 392 // Copy the answer back into the channel and signal the pong event. This 393 // should wake up the client so he can finish the the ipc cycle. 394 CrossCallParams* call_params = reinterpret_cast<CrossCallParams*>(buffer); 395 memcpy(call_params->GetCallReturn(), &call_result, sizeof(call_result)); 396 ::InterlockedExchange(&service_context->channel->state, kAckChannel); 397 ::SetEvent(service_context->pong_event); 398 } 399 400 bool SharedMemIPCServer::MakeEvents(HANDLE* server_ping, HANDLE* server_pong, 401 HANDLE* client_ping, HANDLE* client_pong) { 402 // Note that the IPC client has no right to delete the events. That would 403 // cause problems. The server *owns* the events. 404 const DWORD kDesiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE; 405 406 // The events are auto reset, and start not signaled. 407 *server_ping = ::CreateEventW(NULL, FALSE, FALSE, NULL); 408 if (!::DuplicateHandle(::GetCurrentProcess(), *server_ping, target_process_, 409 client_ping, kDesiredAccess, FALSE, 0)) { 410 return false; 411 } 412 *server_pong = ::CreateEventW(NULL, FALSE, FALSE, NULL); 413 if (!::DuplicateHandle(::GetCurrentProcess(), *server_pong, target_process_, 414 client_pong, kDesiredAccess, FALSE, 0)) { 415 return false; 416 } 417 return true; 418 } 419 420 } // namespace sandbox 421