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 "sandbox/win/src/sandbox_policy_base.h" 6 7 #include "base/basictypes.h" 8 #include "base/callback.h" 9 #include "base/logging.h" 10 #include "base/win/windows_version.h" 11 #include "sandbox/win/src/app_container.h" 12 #include "sandbox/win/src/filesystem_dispatcher.h" 13 #include "sandbox/win/src/filesystem_policy.h" 14 #include "sandbox/win/src/handle_dispatcher.h" 15 #include "sandbox/win/src/handle_policy.h" 16 #include "sandbox/win/src/job.h" 17 #include "sandbox/win/src/interception.h" 18 #include "sandbox/win/src/process_mitigations.h" 19 #include "sandbox/win/src/named_pipe_dispatcher.h" 20 #include "sandbox/win/src/named_pipe_policy.h" 21 #include "sandbox/win/src/policy_broker.h" 22 #include "sandbox/win/src/policy_engine_processor.h" 23 #include "sandbox/win/src/policy_low_level.h" 24 #include "sandbox/win/src/process_thread_dispatcher.h" 25 #include "sandbox/win/src/process_thread_policy.h" 26 #include "sandbox/win/src/registry_dispatcher.h" 27 #include "sandbox/win/src/registry_policy.h" 28 #include "sandbox/win/src/restricted_token_utils.h" 29 #include "sandbox/win/src/sandbox_policy.h" 30 #include "sandbox/win/src/sync_dispatcher.h" 31 #include "sandbox/win/src/sync_policy.h" 32 #include "sandbox/win/src/target_process.h" 33 #include "sandbox/win/src/window.h" 34 35 namespace { 36 37 // The standard windows size for one memory page. 38 const size_t kOneMemPage = 4096; 39 // The IPC and Policy shared memory sizes. 40 const size_t kIPCMemSize = kOneMemPage * 2; 41 const size_t kPolMemSize = kOneMemPage * 14; 42 43 // Helper function to allocate space (on the heap) for policy. 44 sandbox::PolicyGlobal* MakeBrokerPolicyMemory() { 45 const size_t kTotalPolicySz = kPolMemSize; 46 sandbox::PolicyGlobal* policy = static_cast<sandbox::PolicyGlobal*> 47 (::operator new(kTotalPolicySz)); 48 DCHECK(policy); 49 memset(policy, 0, kTotalPolicySz); 50 policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal); 51 return policy; 52 } 53 54 bool IsInheritableHandle(HANDLE handle) { 55 if (!handle) 56 return false; 57 if (handle == INVALID_HANDLE_VALUE) 58 return false; 59 // File handles (FILE_TYPE_DISK) and pipe handles are known to be 60 // inheritable. Console handles (FILE_TYPE_CHAR) are not 61 // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST. 62 DWORD handle_type = GetFileType(handle); 63 return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE; 64 } 65 66 } 67 68 namespace sandbox { 69 70 SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level; 71 SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations; 72 73 // Initializes static members. 74 HWINSTA PolicyBase::alternate_winstation_handle_ = NULL; 75 HDESK PolicyBase::alternate_desktop_handle_ = NULL; 76 77 PolicyBase::PolicyBase() 78 : ref_count(1), 79 lockdown_level_(USER_LOCKDOWN), 80 initial_level_(USER_LOCKDOWN), 81 job_level_(JOB_LOCKDOWN), 82 ui_exceptions_(0), 83 use_alternate_desktop_(false), 84 use_alternate_winstation_(false), 85 file_system_init_(false), 86 relaxed_interceptions_(true), 87 stdout_handle_(INVALID_HANDLE_VALUE), 88 stderr_handle_(INVALID_HANDLE_VALUE), 89 integrity_level_(INTEGRITY_LEVEL_LAST), 90 delayed_integrity_level_(INTEGRITY_LEVEL_LAST), 91 mitigations_(0), 92 delayed_mitigations_(0), 93 policy_maker_(NULL), 94 policy_(NULL) { 95 ::InitializeCriticalSection(&lock_); 96 // Initialize the IPC dispatcher array. 97 memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); 98 Dispatcher* dispatcher = NULL; 99 100 dispatcher = new FilesystemDispatcher(this); 101 ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; 102 ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; 103 ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; 104 ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; 105 ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; 106 107 dispatcher = new NamedPipeDispatcher(this); 108 ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; 109 110 dispatcher = new ThreadProcessDispatcher(this); 111 ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; 112 ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; 113 ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; 114 ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; 115 ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; 116 117 dispatcher = new SyncDispatcher(this); 118 ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; 119 ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; 120 121 dispatcher = new RegistryDispatcher(this); 122 ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; 123 ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; 124 125 dispatcher = new HandleDispatcher(this); 126 ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; 127 } 128 129 PolicyBase::~PolicyBase() { 130 TargetSet::iterator it; 131 for (it = targets_.begin(); it != targets_.end(); ++it) { 132 TargetProcess* target = (*it); 133 delete target; 134 } 135 delete ipc_targets_[IPC_NTCREATEFILE_TAG]; 136 delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; 137 delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; 138 delete ipc_targets_[IPC_CREATEEVENT_TAG]; 139 delete ipc_targets_[IPC_NTCREATEKEY_TAG]; 140 delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG]; 141 delete policy_maker_; 142 delete policy_; 143 ::DeleteCriticalSection(&lock_); 144 } 145 146 void PolicyBase::AddRef() { 147 ::InterlockedIncrement(&ref_count); 148 } 149 150 void PolicyBase::Release() { 151 if (0 == ::InterlockedDecrement(&ref_count)) 152 delete this; 153 } 154 155 ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) { 156 if (initial < lockdown) { 157 return SBOX_ERROR_BAD_PARAMS; 158 } 159 initial_level_ = initial; 160 lockdown_level_ = lockdown; 161 return SBOX_ALL_OK; 162 } 163 164 ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) { 165 job_level_ = job_level; 166 ui_exceptions_ = ui_exceptions; 167 return SBOX_ALL_OK; 168 } 169 170 ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) { 171 use_alternate_desktop_ = true; 172 use_alternate_winstation_ = alternate_winstation; 173 return CreateAlternateDesktop(alternate_winstation); 174 } 175 176 string16 PolicyBase::GetAlternateDesktop() const { 177 // No alternate desktop or winstation. Return an empty string. 178 if (!use_alternate_desktop_ && !use_alternate_winstation_) { 179 return string16(); 180 } 181 182 // The desktop and winstation should have been created by now. 183 // If we hit this scenario, it means that the user ignored the failure 184 // during SetAlternateDesktop, so we ignore it here too. 185 if (use_alternate_desktop_ && !alternate_desktop_handle_) { 186 return string16(); 187 } 188 if (use_alternate_winstation_ && (!alternate_desktop_handle_ || 189 !alternate_winstation_handle_)) { 190 return string16(); 191 } 192 193 return GetFullDesktopName(alternate_winstation_handle_, 194 alternate_desktop_handle_); 195 } 196 197 ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) { 198 if (alternate_winstation) { 199 // Previously called with alternate_winstation = false? 200 if (!alternate_winstation_handle_ && alternate_desktop_handle_) 201 return SBOX_ERROR_UNSUPPORTED; 202 203 // Check if it's already created. 204 if (alternate_winstation_handle_ && alternate_desktop_handle_) 205 return SBOX_ALL_OK; 206 207 DCHECK(!alternate_winstation_handle_); 208 // Create the window station. 209 ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_); 210 if (SBOX_ALL_OK != result) 211 return result; 212 213 // Verify that everything is fine. 214 if (!alternate_winstation_handle_ || 215 GetWindowObjectName(alternate_winstation_handle_).empty()) 216 return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 217 218 // Create the destkop. 219 result = CreateAltDesktop(alternate_winstation_handle_, 220 &alternate_desktop_handle_); 221 if (SBOX_ALL_OK != result) 222 return result; 223 224 // Verify that everything is fine. 225 if (!alternate_desktop_handle_ || 226 GetWindowObjectName(alternate_desktop_handle_).empty()) 227 return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 228 } else { 229 // Previously called with alternate_winstation = true? 230 if (alternate_winstation_handle_) 231 return SBOX_ERROR_UNSUPPORTED; 232 233 // Check if it already exists. 234 if (alternate_desktop_handle_) 235 return SBOX_ALL_OK; 236 237 // Create the destkop. 238 ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_); 239 if (SBOX_ALL_OK != result) 240 return result; 241 242 // Verify that everything is fine. 243 if (!alternate_desktop_handle_ || 244 GetWindowObjectName(alternate_desktop_handle_).empty()) 245 return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 246 } 247 248 return SBOX_ALL_OK; 249 } 250 251 void PolicyBase::DestroyAlternateDesktop() { 252 if (alternate_desktop_handle_) { 253 ::CloseDesktop(alternate_desktop_handle_); 254 alternate_desktop_handle_ = NULL; 255 } 256 257 if (alternate_winstation_handle_) { 258 ::CloseWindowStation(alternate_winstation_handle_); 259 alternate_winstation_handle_ = NULL; 260 } 261 } 262 263 ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) { 264 integrity_level_ = integrity_level; 265 return SBOX_ALL_OK; 266 } 267 268 ResultCode PolicyBase::SetDelayedIntegrityLevel( 269 IntegrityLevel integrity_level) { 270 delayed_integrity_level_ = integrity_level; 271 return SBOX_ALL_OK; 272 } 273 274 ResultCode PolicyBase::SetAppContainer(const wchar_t* sid) { 275 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) 276 return SBOX_ALL_OK; 277 278 // Windows refuses to work with an impersonation token for a process inside 279 // an AppContainer. If the caller wants to use a more privileged initial 280 // token, or if the lockdown level will prevent the process from starting, 281 // we have to fail the operation. 282 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) 283 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; 284 285 DCHECK(!appcontainer_list_.get()); 286 appcontainer_list_.reset(new AppContainerAttributes); 287 ResultCode rv = appcontainer_list_->SetAppContainer(sid, capabilities_); 288 if (rv != SBOX_ALL_OK) 289 return rv; 290 291 return SBOX_ALL_OK; 292 } 293 294 ResultCode PolicyBase::SetCapability(const wchar_t* sid) { 295 capabilities_.push_back(sid); 296 return SBOX_ALL_OK; 297 } 298 299 ResultCode PolicyBase::SetProcessMitigations( 300 MitigationFlags flags) { 301 if (!CanSetProcessMitigationsPreStartup(flags)) 302 return SBOX_ERROR_BAD_PARAMS; 303 mitigations_ = flags; 304 return SBOX_ALL_OK; 305 } 306 307 MitigationFlags PolicyBase::GetProcessMitigations() { 308 return mitigations_; 309 } 310 311 ResultCode PolicyBase::SetDelayedProcessMitigations( 312 MitigationFlags flags) { 313 if (!CanSetProcessMitigationsPostStartup(flags)) 314 return SBOX_ERROR_BAD_PARAMS; 315 delayed_mitigations_ = flags; 316 return SBOX_ALL_OK; 317 } 318 319 MitigationFlags PolicyBase::GetDelayedProcessMitigations() { 320 return delayed_mitigations_; 321 } 322 323 void PolicyBase::SetStrictInterceptions() { 324 relaxed_interceptions_ = false; 325 } 326 327 ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) { 328 if (!IsInheritableHandle(handle)) 329 return SBOX_ERROR_BAD_PARAMS; 330 stdout_handle_ = handle; 331 return SBOX_ALL_OK; 332 } 333 334 ResultCode PolicyBase::SetStderrHandle(HANDLE handle) { 335 if (!IsInheritableHandle(handle)) 336 return SBOX_ERROR_BAD_PARAMS; 337 stderr_handle_ = handle; 338 return SBOX_ALL_OK; 339 } 340 341 ResultCode PolicyBase::AddRule(SubSystem subsystem, Semantics semantics, 342 const wchar_t* pattern) { 343 if (NULL == policy_) { 344 policy_ = MakeBrokerPolicyMemory(); 345 DCHECK(policy_); 346 policy_maker_ = new LowLevelPolicy(policy_); 347 DCHECK(policy_maker_); 348 } 349 350 switch (subsystem) { 351 case SUBSYS_FILES: { 352 if (!file_system_init_) { 353 if (!FileSystemPolicy::SetInitialRules(policy_maker_)) 354 return SBOX_ERROR_BAD_PARAMS; 355 file_system_init_ = true; 356 } 357 if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 358 NOTREACHED(); 359 return SBOX_ERROR_BAD_PARAMS; 360 } 361 break; 362 } 363 case SUBSYS_SYNC: { 364 if (!SyncPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 365 NOTREACHED(); 366 return SBOX_ERROR_BAD_PARAMS; 367 } 368 break; 369 } 370 case SUBSYS_PROCESS: { 371 if (lockdown_level_ < USER_INTERACTIVE && 372 TargetPolicy::PROCESS_ALL_EXEC == semantics) { 373 // This is unsupported. This is a huge security risk to give full access 374 // to a process handle. 375 return SBOX_ERROR_UNSUPPORTED; 376 } 377 if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 378 NOTREACHED(); 379 return SBOX_ERROR_BAD_PARAMS; 380 } 381 break; 382 } 383 case SUBSYS_NAMED_PIPES: { 384 if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) { 385 NOTREACHED(); 386 return SBOX_ERROR_BAD_PARAMS; 387 } 388 break; 389 } 390 case SUBSYS_REGISTRY: { 391 if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 392 NOTREACHED(); 393 return SBOX_ERROR_BAD_PARAMS; 394 } 395 break; 396 } 397 case SUBSYS_HANDLES: { 398 if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) { 399 NOTREACHED(); 400 return SBOX_ERROR_BAD_PARAMS; 401 } 402 break; 403 } 404 default: { 405 return SBOX_ERROR_UNSUPPORTED; 406 } 407 } 408 409 return SBOX_ALL_OK; 410 } 411 412 ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) { 413 blacklisted_dlls_.push_back(dll_name); 414 return SBOX_ALL_OK; 415 } 416 417 ResultCode PolicyBase::AddKernelObjectToClose(const char16* handle_type, 418 const char16* handle_name) { 419 return handle_closer_.AddHandle(handle_type, handle_name); 420 } 421 422 // When an IPC is ready in any of the targets we get called. We manage an array 423 // of IPC dispatchers which are keyed on the IPC tag so we normally delegate 424 // to the appropriate dispatcher unless we can handle the IPC call ourselves. 425 Dispatcher* PolicyBase::OnMessageReady(IPCParams* ipc, 426 CallbackGeneric* callback) { 427 DCHECK(callback); 428 static const IPCParams ping1 = {IPC_PING1_TAG, ULONG_TYPE}; 429 static const IPCParams ping2 = {IPC_PING2_TAG, INOUTPTR_TYPE}; 430 431 if (ping1.Matches(ipc) || ping2.Matches(ipc)) { 432 *callback = reinterpret_cast<CallbackGeneric>( 433 static_cast<Callback1>(&PolicyBase::Ping)); 434 return this; 435 } 436 437 Dispatcher* dispatch = GetDispatcher(ipc->ipc_tag); 438 if (!dispatch) { 439 NOTREACHED(); 440 return NULL; 441 } 442 return dispatch->OnMessageReady(ipc, callback); 443 } 444 445 // Delegate to the appropriate dispatcher. 446 bool PolicyBase::SetupService(InterceptionManager* manager, int service) { 447 if (IPC_PING1_TAG == service || IPC_PING2_TAG == service) 448 return true; 449 450 Dispatcher* dispatch = GetDispatcher(service); 451 if (!dispatch) { 452 NOTREACHED(); 453 return false; 454 } 455 return dispatch->SetupService(manager, service); 456 } 457 458 ResultCode PolicyBase::MakeJobObject(HANDLE* job) { 459 if (job_level_ != JOB_NONE) { 460 // Create the windows job object. 461 Job job_obj; 462 DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_); 463 if (ERROR_SUCCESS != result) { 464 return SBOX_ERROR_GENERIC; 465 } 466 *job = job_obj.Detach(); 467 } else { 468 *job = NULL; 469 } 470 return SBOX_ALL_OK; 471 } 472 473 ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { 474 // Create the 'naked' token. This will be the permanent token associated 475 // with the process and therefore with any thread that is not impersonating. 476 DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, 477 integrity_level_, PRIMARY); 478 if (ERROR_SUCCESS != result) { 479 return SBOX_ERROR_GENERIC; 480 } 481 482 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { 483 // Windows refuses to work with an impersonation token. See SetAppContainer 484 // implementation for more details. 485 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) 486 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; 487 488 *initial = INVALID_HANDLE_VALUE; 489 return SBOX_ALL_OK; 490 } 491 492 // Create the 'better' token. We use this token as the one that the main 493 // thread uses when booting up the process. It should contain most of 494 // what we need (before reaching main( )) 495 result = CreateRestrictedToken(initial, initial_level_, 496 integrity_level_, IMPERSONATION); 497 if (ERROR_SUCCESS != result) { 498 ::CloseHandle(*lockdown); 499 return SBOX_ERROR_GENERIC; 500 } 501 return SBOX_ALL_OK; 502 } 503 504 const AppContainerAttributes* PolicyBase::GetAppContainer() { 505 if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) 506 return NULL; 507 508 return appcontainer_list_.get(); 509 } 510 511 bool PolicyBase::AddTarget(TargetProcess* target) { 512 if (NULL != policy_) 513 policy_maker_->Done(); 514 515 if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), 516 mitigations_)) { 517 return false; 518 } 519 520 if (!SetupAllInterceptions(target)) 521 return false; 522 523 if (!SetupHandleCloser(target)) 524 return false; 525 526 // Initialize the sandbox infrastructure for the target. 527 if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize)) 528 return false; 529 530 g_shared_delayed_integrity_level = delayed_integrity_level_; 531 ResultCode ret = target->TransferVariable( 532 "g_shared_delayed_integrity_level", 533 &g_shared_delayed_integrity_level, 534 sizeof(g_shared_delayed_integrity_level)); 535 g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; 536 if (SBOX_ALL_OK != ret) 537 return false; 538 539 // Add in delayed mitigations and pseudo-mitigations enforced at startup. 540 g_shared_delayed_mitigations = delayed_mitigations_ | 541 FilterPostStartupProcessMitigations(mitigations_); 542 if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations)) 543 return false; 544 545 ret = target->TransferVariable("g_shared_delayed_mitigations", 546 &g_shared_delayed_mitigations, 547 sizeof(g_shared_delayed_mitigations)); 548 g_shared_delayed_mitigations = 0; 549 if (SBOX_ALL_OK != ret) 550 return false; 551 552 AutoLock lock(&lock_); 553 targets_.push_back(target); 554 return true; 555 } 556 557 bool PolicyBase::OnJobEmpty(HANDLE job) { 558 AutoLock lock(&lock_); 559 TargetSet::iterator it; 560 for (it = targets_.begin(); it != targets_.end(); ++it) { 561 if ((*it)->Job() == job) 562 break; 563 } 564 if (it == targets_.end()) { 565 return false; 566 } 567 TargetProcess* target = *it; 568 targets_.erase(it); 569 delete target; 570 return true; 571 } 572 573 EvalResult PolicyBase::EvalPolicy(int service, 574 CountedParameterSetBase* params) { 575 if (NULL != policy_) { 576 if (NULL == policy_->entry[service]) { 577 // There is no policy for this particular service. This is not a big 578 // deal. 579 return DENY_ACCESS; 580 } 581 for (int i = 0; i < params->count; i++) { 582 if (!params->parameters[i].IsValid()) { 583 NOTREACHED(); 584 return SIGNAL_ALARM; 585 } 586 } 587 PolicyProcessor pol_evaluator(policy_->entry[service]); 588 PolicyResult result = pol_evaluator.Evaluate(kShortEval, 589 params->parameters, 590 params->count); 591 if (POLICY_MATCH == result) { 592 return pol_evaluator.GetAction(); 593 } 594 DCHECK(POLICY_ERROR != result); 595 } 596 597 return DENY_ACCESS; 598 } 599 600 HANDLE PolicyBase::GetStdoutHandle() { 601 return stdout_handle_; 602 } 603 604 HANDLE PolicyBase::GetStderrHandle() { 605 return stderr_handle_; 606 } 607 608 // We service IPC_PING_TAG message which is a way to test a round trip of the 609 // IPC subsystem. We receive a integer cookie and we are expected to return the 610 // cookie times two (or three) and the current tick count. 611 bool PolicyBase::Ping(IPCInfo* ipc, void* arg1) { 612 switch (ipc->ipc_tag) { 613 case IPC_PING1_TAG: { 614 IPCInt ipc_int(arg1); 615 uint32 cookie = ipc_int.As32Bit(); 616 ipc->return_info.extended_count = 2; 617 ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); 618 ipc->return_info.extended[1].unsigned_int = 2 * cookie; 619 return true; 620 } 621 case IPC_PING2_TAG: { 622 CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); 623 if (sizeof(uint32) != io_buffer->Size()) 624 return false; 625 626 uint32* cookie = reinterpret_cast<uint32*>(io_buffer->Buffer()); 627 *cookie = (*cookie) * 3; 628 return true; 629 } 630 default: return false; 631 } 632 } 633 634 Dispatcher* PolicyBase::GetDispatcher(int ipc_tag) { 635 if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG) 636 return NULL; 637 638 return ipc_targets_[ipc_tag]; 639 } 640 641 bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { 642 InterceptionManager manager(target, relaxed_interceptions_); 643 644 if (policy_) { 645 for (int i = 0; i < IPC_LAST_TAG; i++) { 646 if (policy_->entry[i] && !ipc_targets_[i]->SetupService(&manager, i)) 647 return false; 648 } 649 } 650 651 if (!blacklisted_dlls_.empty()) { 652 std::vector<string16>::iterator it = blacklisted_dlls_.begin(); 653 for (; it != blacklisted_dlls_.end(); ++it) { 654 manager.AddToUnloadModules(it->c_str()); 655 } 656 } 657 658 if (!handle_closer_.SetupHandleInterceptions(&manager)) 659 return false; 660 661 if (!SetupBasicInterceptions(&manager)) 662 return false; 663 664 if (!manager.InitializeInterceptions()) 665 return false; 666 667 // Finally, setup imports on the target so the interceptions can work. 668 return SetupNtdllImports(target); 669 } 670 671 bool PolicyBase::SetupHandleCloser(TargetProcess* target) { 672 return handle_closer_.InitializeTargetHandles(target); 673 } 674 675 } // namespace sandbox 676