| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/win/src/sandbox_policy_base.h" | 5 #include "sandbox/win/src/sandbox_policy_base.h" |
| 6 | 6 |
| 7 #include <sddl.h> | 7 #include <sddl.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" |
| 12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 13 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 14 #include "base/win/windows_version.h" | 15 #include "base/win/windows_version.h" |
| 15 #include "sandbox/win/src/app_container.h" | 16 #include "sandbox/win/src/app_container.h" |
| 16 #include "sandbox/win/src/filesystem_dispatcher.h" | |
| 17 #include "sandbox/win/src/filesystem_policy.h" | 17 #include "sandbox/win/src/filesystem_policy.h" |
| 18 #include "sandbox/win/src/handle_dispatcher.h" | |
| 19 #include "sandbox/win/src/handle_policy.h" | 18 #include "sandbox/win/src/handle_policy.h" |
| 19 #include "sandbox/win/src/interception.h" |
| 20 #include "sandbox/win/src/job.h" | 20 #include "sandbox/win/src/job.h" |
| 21 #include "sandbox/win/src/interception.h" | |
| 22 #include "sandbox/win/src/process_mitigations.h" | |
| 23 #include "sandbox/win/src/named_pipe_dispatcher.h" | |
| 24 #include "sandbox/win/src/named_pipe_policy.h" | 21 #include "sandbox/win/src/named_pipe_policy.h" |
| 25 #include "sandbox/win/src/policy_broker.h" | 22 #include "sandbox/win/src/policy_broker.h" |
| 26 #include "sandbox/win/src/policy_engine_processor.h" | 23 #include "sandbox/win/src/policy_engine_processor.h" |
| 27 #include "sandbox/win/src/policy_low_level.h" | 24 #include "sandbox/win/src/policy_low_level.h" |
| 28 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" | 25 #include "sandbox/win/src/process_mitigations.h" |
| 29 #include "sandbox/win/src/process_mitigations_win32k_policy.h" | 26 #include "sandbox/win/src/process_mitigations_win32k_policy.h" |
| 30 #include "sandbox/win/src/process_thread_dispatcher.h" | |
| 31 #include "sandbox/win/src/process_thread_policy.h" | 27 #include "sandbox/win/src/process_thread_policy.h" |
| 32 #include "sandbox/win/src/registry_dispatcher.h" | |
| 33 #include "sandbox/win/src/registry_policy.h" | 28 #include "sandbox/win/src/registry_policy.h" |
| 34 #include "sandbox/win/src/restricted_token_utils.h" | 29 #include "sandbox/win/src/restricted_token_utils.h" |
| 35 #include "sandbox/win/src/sandbox_policy.h" | 30 #include "sandbox/win/src/sandbox_policy.h" |
| 36 #include "sandbox/win/src/sandbox_utils.h" | 31 #include "sandbox/win/src/sandbox_utils.h" |
| 37 #include "sandbox/win/src/sync_dispatcher.h" | |
| 38 #include "sandbox/win/src/sync_policy.h" | 32 #include "sandbox/win/src/sync_policy.h" |
| 39 #include "sandbox/win/src/target_process.h" | 33 #include "sandbox/win/src/target_process.h" |
| 34 #include "sandbox/win/src/top_level_dispatcher.h" |
| 40 #include "sandbox/win/src/window.h" | 35 #include "sandbox/win/src/window.h" |
| 41 | 36 |
| 42 namespace { | 37 namespace { |
| 43 | 38 |
| 44 // The standard windows size for one memory page. | 39 // The standard windows size for one memory page. |
| 45 const size_t kOneMemPage = 4096; | 40 const size_t kOneMemPage = 4096; |
| 46 // The IPC and Policy shared memory sizes. | 41 // The IPC and Policy shared memory sizes. |
| 47 const size_t kIPCMemSize = kOneMemPage * 2; | 42 const size_t kIPCMemSize = kOneMemPage * 2; |
| 48 const size_t kPolMemSize = kOneMemPage * 14; | 43 const size_t kPolMemSize = kOneMemPage * 14; |
| 49 | 44 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 NTSTATUS status = CreateObjectDirectory(&handle, | 95 NTSTATUS status = CreateObjectDirectory(&handle, |
| 101 DIRECTORY_ALL_ACCESS, | 96 DIRECTORY_ALL_ACCESS, |
| 102 &obj_attr); | 97 &obj_attr); |
| 103 | 98 |
| 104 if (!NT_SUCCESS(status)) | 99 if (!NT_SUCCESS(status)) |
| 105 return NULL; | 100 return NULL; |
| 106 | 101 |
| 107 return handle; | 102 return handle; |
| 108 } | 103 } |
| 109 | 104 |
| 110 } | 105 } // namespace |
| 111 | 106 |
| 112 namespace sandbox { | 107 namespace sandbox { |
| 113 | 108 |
| 114 SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level; | 109 SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level; |
| 115 SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations; | 110 SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations; |
| 116 | 111 |
| 117 // Initializes static members. | 112 // Initializes static members. |
| 118 HWINSTA PolicyBase::alternate_winstation_handle_ = NULL; | 113 HWINSTA PolicyBase::alternate_winstation_handle_ = NULL; |
| 119 HDESK PolicyBase::alternate_desktop_handle_ = NULL; | 114 HDESK PolicyBase::alternate_desktop_handle_ = NULL; |
| 120 IntegrityLevel PolicyBase::alternate_desktop_integrity_level_label_ = | 115 IntegrityLevel PolicyBase::alternate_desktop_integrity_level_label_ = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 134 stdout_handle_(INVALID_HANDLE_VALUE), | 129 stdout_handle_(INVALID_HANDLE_VALUE), |
| 135 stderr_handle_(INVALID_HANDLE_VALUE), | 130 stderr_handle_(INVALID_HANDLE_VALUE), |
| 136 integrity_level_(INTEGRITY_LEVEL_LAST), | 131 integrity_level_(INTEGRITY_LEVEL_LAST), |
| 137 delayed_integrity_level_(INTEGRITY_LEVEL_LAST), | 132 delayed_integrity_level_(INTEGRITY_LEVEL_LAST), |
| 138 mitigations_(0), | 133 mitigations_(0), |
| 139 delayed_mitigations_(0), | 134 delayed_mitigations_(0), |
| 140 policy_maker_(NULL), | 135 policy_maker_(NULL), |
| 141 policy_(NULL), | 136 policy_(NULL), |
| 142 lowbox_sid_(NULL) { | 137 lowbox_sid_(NULL) { |
| 143 ::InitializeCriticalSection(&lock_); | 138 ::InitializeCriticalSection(&lock_); |
| 144 // Initialize the IPC dispatcher array. | 139 dispatcher_.reset(new TopLevelDispatcher(this)); |
| 145 memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); | |
| 146 Dispatcher* dispatcher = NULL; | |
| 147 | |
| 148 dispatcher = new FilesystemDispatcher(this); | |
| 149 ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; | |
| 150 ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; | |
| 151 ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; | |
| 152 ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; | |
| 153 ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; | |
| 154 | |
| 155 dispatcher = new NamedPipeDispatcher(this); | |
| 156 ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; | |
| 157 | |
| 158 dispatcher = new ThreadProcessDispatcher(this); | |
| 159 ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; | |
| 160 ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; | |
| 161 ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; | |
| 162 ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; | |
| 163 ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; | |
| 164 | |
| 165 dispatcher = new SyncDispatcher(this); | |
| 166 ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; | |
| 167 ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; | |
| 168 | |
| 169 dispatcher = new RegistryDispatcher(this); | |
| 170 ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; | |
| 171 ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; | |
| 172 | |
| 173 dispatcher = new HandleDispatcher(this); | |
| 174 ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; | |
| 175 | |
| 176 dispatcher = new ProcessMitigationsWin32KDispatcher(this); | |
| 177 ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher; | |
| 178 ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher; | |
| 179 ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher; | |
| 180 } | 140 } |
| 181 | 141 |
| 182 PolicyBase::~PolicyBase() { | 142 PolicyBase::~PolicyBase() { |
| 183 ClearSharedHandles(); | 143 ClearSharedHandles(); |
| 184 | 144 |
| 185 TargetSet::iterator it; | 145 TargetSet::iterator it; |
| 186 for (it = targets_.begin(); it != targets_.end(); ++it) { | 146 for (it = targets_.begin(); it != targets_.end(); ++it) { |
| 187 TargetProcess* target = (*it); | 147 TargetProcess* target = (*it); |
| 188 delete target; | 148 delete target; |
| 189 } | 149 } |
| 190 delete ipc_targets_[IPC_NTCREATEFILE_TAG]; | |
| 191 delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; | |
| 192 delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; | |
| 193 delete ipc_targets_[IPC_CREATEEVENT_TAG]; | |
| 194 delete ipc_targets_[IPC_NTCREATEKEY_TAG]; | |
| 195 delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG]; | |
| 196 delete policy_maker_; | 150 delete policy_maker_; |
| 197 delete policy_; | 151 delete policy_; |
| 198 | 152 |
| 199 if (lowbox_sid_) | 153 if (lowbox_sid_) |
| 200 ::LocalFree(lowbox_sid_); | 154 ::LocalFree(lowbox_sid_); |
| 201 | 155 |
| 202 ::DeleteCriticalSection(&lock_); | 156 ::DeleteCriticalSection(&lock_); |
| 203 } | 157 } |
| 204 | 158 |
| 205 void PolicyBase::AddRef() { | 159 void PolicyBase::AddRef() { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 } | 436 } |
| 483 | 437 |
| 484 const HandleList& PolicyBase::GetHandlesBeingShared() { | 438 const HandleList& PolicyBase::GetHandlesBeingShared() { |
| 485 return handles_to_share_; | 439 return handles_to_share_; |
| 486 } | 440 } |
| 487 | 441 |
| 488 void PolicyBase::ClearSharedHandles() { | 442 void PolicyBase::ClearSharedHandles() { |
| 489 STLDeleteElements(&handles_to_share_); | 443 STLDeleteElements(&handles_to_share_); |
| 490 } | 444 } |
| 491 | 445 |
| 492 // When an IPC is ready in any of the targets we get called. We manage an array | |
| 493 // of IPC dispatchers which are keyed on the IPC tag so we normally delegate | |
| 494 // to the appropriate dispatcher unless we can handle the IPC call ourselves. | |
| 495 Dispatcher* PolicyBase::OnMessageReady(IPCParams* ipc, | |
| 496 CallbackGeneric* callback) { | |
| 497 DCHECK(callback); | |
| 498 static const IPCParams ping1 = {IPC_PING1_TAG, {UINT32_TYPE}}; | |
| 499 static const IPCParams ping2 = {IPC_PING2_TAG, {INOUTPTR_TYPE}}; | |
| 500 | |
| 501 if (ping1.Matches(ipc) || ping2.Matches(ipc)) { | |
| 502 *callback = reinterpret_cast<CallbackGeneric>( | |
| 503 static_cast<Callback1>(&PolicyBase::Ping)); | |
| 504 return this; | |
| 505 } | |
| 506 | |
| 507 Dispatcher* dispatch = GetDispatcher(ipc->ipc_tag); | |
| 508 if (!dispatch) { | |
| 509 NOTREACHED(); | |
| 510 return NULL; | |
| 511 } | |
| 512 return dispatch->OnMessageReady(ipc, callback); | |
| 513 } | |
| 514 | |
| 515 // Delegate to the appropriate dispatcher. | |
| 516 bool PolicyBase::SetupService(InterceptionManager* manager, int service) { | |
| 517 if (IPC_PING1_TAG == service || IPC_PING2_TAG == service) | |
| 518 return true; | |
| 519 | |
| 520 Dispatcher* dispatch = GetDispatcher(service); | |
| 521 if (!dispatch) { | |
| 522 NOTREACHED(); | |
| 523 return false; | |
| 524 } | |
| 525 return dispatch->SetupService(manager, service); | |
| 526 } | |
| 527 | |
| 528 ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) { | 446 ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) { |
| 529 if (job_level_ != JOB_NONE) { | 447 if (job_level_ != JOB_NONE) { |
| 530 // Create the windows job object. | 448 // Create the windows job object. |
| 531 Job job_obj; | 449 Job job_obj; |
| 532 DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_, | 450 DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_, |
| 533 memory_limit_); | 451 memory_limit_); |
| 534 if (ERROR_SUCCESS != result) | 452 if (ERROR_SUCCESS != result) |
| 535 return SBOX_ERROR_GENERIC; | 453 return SBOX_ERROR_GENERIC; |
| 536 | 454 |
| 537 *job = job_obj.Take(); | 455 *job = job_obj.Take(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 return false; | 566 return false; |
| 649 } | 567 } |
| 650 | 568 |
| 651 if (!SetupAllInterceptions(target)) | 569 if (!SetupAllInterceptions(target)) |
| 652 return false; | 570 return false; |
| 653 | 571 |
| 654 if (!SetupHandleCloser(target)) | 572 if (!SetupHandleCloser(target)) |
| 655 return false; | 573 return false; |
| 656 | 574 |
| 657 // Initialize the sandbox infrastructure for the target. | 575 // Initialize the sandbox infrastructure for the target. |
| 658 if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize)) | 576 if (ERROR_SUCCESS != |
| 577 target->Init(dispatcher_.get(), policy_, kIPCMemSize, kPolMemSize)) |
| 659 return false; | 578 return false; |
| 660 | 579 |
| 661 g_shared_delayed_integrity_level = delayed_integrity_level_; | 580 g_shared_delayed_integrity_level = delayed_integrity_level_; |
| 662 ResultCode ret = target->TransferVariable( | 581 ResultCode ret = target->TransferVariable( |
| 663 "g_shared_delayed_integrity_level", | 582 "g_shared_delayed_integrity_level", |
| 664 &g_shared_delayed_integrity_level, | 583 &g_shared_delayed_integrity_level, |
| 665 sizeof(g_shared_delayed_integrity_level)); | 584 sizeof(g_shared_delayed_integrity_level)); |
| 666 g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; | 585 g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; |
| 667 if (SBOX_ALL_OK != ret) | 586 if (SBOX_ALL_OK != ret) |
| 668 return false; | 587 return false; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 } | 648 } |
| 730 | 649 |
| 731 HANDLE PolicyBase::GetStdoutHandle() { | 650 HANDLE PolicyBase::GetStdoutHandle() { |
| 732 return stdout_handle_; | 651 return stdout_handle_; |
| 733 } | 652 } |
| 734 | 653 |
| 735 HANDLE PolicyBase::GetStderrHandle() { | 654 HANDLE PolicyBase::GetStderrHandle() { |
| 736 return stderr_handle_; | 655 return stderr_handle_; |
| 737 } | 656 } |
| 738 | 657 |
| 739 // We service IPC_PING_TAG message which is a way to test a round trip of the | |
| 740 // IPC subsystem. We receive a integer cookie and we are expected to return the | |
| 741 // cookie times two (or three) and the current tick count. | |
| 742 bool PolicyBase::Ping(IPCInfo* ipc, void* arg1) { | |
| 743 switch (ipc->ipc_tag) { | |
| 744 case IPC_PING1_TAG: { | |
| 745 IPCInt ipc_int(arg1); | |
| 746 uint32 cookie = ipc_int.As32Bit(); | |
| 747 ipc->return_info.extended_count = 2; | |
| 748 ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); | |
| 749 ipc->return_info.extended[1].unsigned_int = 2 * cookie; | |
| 750 return true; | |
| 751 } | |
| 752 case IPC_PING2_TAG: { | |
| 753 CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); | |
| 754 if (sizeof(uint32) != io_buffer->Size()) | |
| 755 return false; | |
| 756 | |
| 757 uint32* cookie = reinterpret_cast<uint32*>(io_buffer->Buffer()); | |
| 758 *cookie = (*cookie) * 3; | |
| 759 return true; | |
| 760 } | |
| 761 default: return false; | |
| 762 } | |
| 763 } | |
| 764 | |
| 765 Dispatcher* PolicyBase::GetDispatcher(int ipc_tag) { | |
| 766 if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG) | |
| 767 return NULL; | |
| 768 | |
| 769 return ipc_targets_[ipc_tag]; | |
| 770 } | |
| 771 | |
| 772 bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { | 658 bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { |
| 773 InterceptionManager manager(target, relaxed_interceptions_); | 659 InterceptionManager manager(target, relaxed_interceptions_); |
| 774 | 660 |
| 775 if (policy_) { | 661 if (policy_) { |
| 776 for (int i = 0; i < IPC_LAST_TAG; i++) { | 662 for (int i = 0; i < IPC_LAST_TAG; i++) { |
| 777 if (policy_->entry[i] && !ipc_targets_[i]->SetupService(&manager, i)) | 663 if (policy_->entry[i] && !dispatcher_->SetupService(&manager, i)) |
| 778 return false; | 664 return false; |
| 779 } | 665 } |
| 780 } | 666 } |
| 781 | 667 |
| 782 if (!blacklisted_dlls_.empty()) { | 668 if (!blacklisted_dlls_.empty()) { |
| 783 std::vector<base::string16>::iterator it = blacklisted_dlls_.begin(); | 669 std::vector<base::string16>::iterator it = blacklisted_dlls_.begin(); |
| 784 for (; it != blacklisted_dlls_.end(); ++it) { | 670 for (; it != blacklisted_dlls_.end(); ++it) { |
| 785 manager.AddToUnloadModules(it->c_str()); | 671 manager.AddToUnloadModules(it->c_str()); |
| 786 } | 672 } |
| 787 } | 673 } |
| 788 | 674 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 break; | 760 break; |
| 875 } | 761 } |
| 876 | 762 |
| 877 default: { return SBOX_ERROR_UNSUPPORTED; } | 763 default: { return SBOX_ERROR_UNSUPPORTED; } |
| 878 } | 764 } |
| 879 | 765 |
| 880 return SBOX_ALL_OK; | 766 return SBOX_ALL_OK; |
| 881 } | 767 } |
| 882 | 768 |
| 883 } // namespace sandbox | 769 } // namespace sandbox |
| OLD | NEW |