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