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