1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/sandbox_policy_base.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,675 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "sandbox/win/src/sandbox_policy_base.h" 1.9 + 1.10 +#include "base/basictypes.h" 1.11 +#include "base/callback.h" 1.12 +#include "base/logging.h" 1.13 +#include "base/win/windows_version.h" 1.14 +#include "sandbox/win/src/app_container.h" 1.15 +#include "sandbox/win/src/filesystem_dispatcher.h" 1.16 +#include "sandbox/win/src/filesystem_policy.h" 1.17 +#include "sandbox/win/src/handle_dispatcher.h" 1.18 +#include "sandbox/win/src/handle_policy.h" 1.19 +#include "sandbox/win/src/job.h" 1.20 +#include "sandbox/win/src/interception.h" 1.21 +#include "sandbox/win/src/process_mitigations.h" 1.22 +#include "sandbox/win/src/named_pipe_dispatcher.h" 1.23 +#include "sandbox/win/src/named_pipe_policy.h" 1.24 +#include "sandbox/win/src/policy_broker.h" 1.25 +#include "sandbox/win/src/policy_engine_processor.h" 1.26 +#include "sandbox/win/src/policy_low_level.h" 1.27 +#include "sandbox/win/src/process_thread_dispatcher.h" 1.28 +#include "sandbox/win/src/process_thread_policy.h" 1.29 +#include "sandbox/win/src/registry_dispatcher.h" 1.30 +#include "sandbox/win/src/registry_policy.h" 1.31 +#include "sandbox/win/src/restricted_token_utils.h" 1.32 +#include "sandbox/win/src/sandbox_policy.h" 1.33 +#include "sandbox/win/src/sync_dispatcher.h" 1.34 +#include "sandbox/win/src/sync_policy.h" 1.35 +#include "sandbox/win/src/target_process.h" 1.36 +#include "sandbox/win/src/window.h" 1.37 + 1.38 +namespace { 1.39 + 1.40 +// The standard windows size for one memory page. 1.41 +const size_t kOneMemPage = 4096; 1.42 +// The IPC and Policy shared memory sizes. 1.43 +const size_t kIPCMemSize = kOneMemPage * 2; 1.44 +const size_t kPolMemSize = kOneMemPage * 14; 1.45 + 1.46 +// Helper function to allocate space (on the heap) for policy. 1.47 +sandbox::PolicyGlobal* MakeBrokerPolicyMemory() { 1.48 + const size_t kTotalPolicySz = kPolMemSize; 1.49 + sandbox::PolicyGlobal* policy = static_cast<sandbox::PolicyGlobal*> 1.50 + (::operator new(kTotalPolicySz)); 1.51 + DCHECK(policy); 1.52 + memset(policy, 0, kTotalPolicySz); 1.53 + policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal); 1.54 + return policy; 1.55 +} 1.56 + 1.57 +bool IsInheritableHandle(HANDLE handle) { 1.58 + if (!handle) 1.59 + return false; 1.60 + if (handle == INVALID_HANDLE_VALUE) 1.61 + return false; 1.62 + // File handles (FILE_TYPE_DISK) and pipe handles are known to be 1.63 + // inheritable. Console handles (FILE_TYPE_CHAR) are not 1.64 + // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST. 1.65 + DWORD handle_type = GetFileType(handle); 1.66 + return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE; 1.67 +} 1.68 + 1.69 +} 1.70 + 1.71 +namespace sandbox { 1.72 + 1.73 +SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level; 1.74 +SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations; 1.75 + 1.76 +// Initializes static members. 1.77 +HWINSTA PolicyBase::alternate_winstation_handle_ = NULL; 1.78 +HDESK PolicyBase::alternate_desktop_handle_ = NULL; 1.79 + 1.80 +PolicyBase::PolicyBase() 1.81 + : ref_count(1), 1.82 + lockdown_level_(USER_LOCKDOWN), 1.83 + initial_level_(USER_LOCKDOWN), 1.84 + job_level_(JOB_LOCKDOWN), 1.85 + ui_exceptions_(0), 1.86 + use_alternate_desktop_(false), 1.87 + use_alternate_winstation_(false), 1.88 + file_system_init_(false), 1.89 + relaxed_interceptions_(true), 1.90 + stdout_handle_(INVALID_HANDLE_VALUE), 1.91 + stderr_handle_(INVALID_HANDLE_VALUE), 1.92 + integrity_level_(INTEGRITY_LEVEL_LAST), 1.93 + delayed_integrity_level_(INTEGRITY_LEVEL_LAST), 1.94 + mitigations_(0), 1.95 + delayed_mitigations_(0), 1.96 + policy_maker_(NULL), 1.97 + policy_(NULL) { 1.98 + ::InitializeCriticalSection(&lock_); 1.99 + // Initialize the IPC dispatcher array. 1.100 + memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); 1.101 + Dispatcher* dispatcher = NULL; 1.102 + 1.103 + dispatcher = new FilesystemDispatcher(this); 1.104 + ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; 1.105 + ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; 1.106 + ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; 1.107 + ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; 1.108 + ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; 1.109 + 1.110 + dispatcher = new NamedPipeDispatcher(this); 1.111 + ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; 1.112 + 1.113 + dispatcher = new ThreadProcessDispatcher(this); 1.114 + ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; 1.115 + ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; 1.116 + ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; 1.117 + ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; 1.118 + ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; 1.119 + 1.120 + dispatcher = new SyncDispatcher(this); 1.121 + ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; 1.122 + ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; 1.123 + 1.124 + dispatcher = new RegistryDispatcher(this); 1.125 + ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; 1.126 + ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; 1.127 + 1.128 + dispatcher = new HandleDispatcher(this); 1.129 + ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; 1.130 +} 1.131 + 1.132 +PolicyBase::~PolicyBase() { 1.133 + TargetSet::iterator it; 1.134 + for (it = targets_.begin(); it != targets_.end(); ++it) { 1.135 + TargetProcess* target = (*it); 1.136 + delete target; 1.137 + } 1.138 + delete ipc_targets_[IPC_NTCREATEFILE_TAG]; 1.139 + delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; 1.140 + delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; 1.141 + delete ipc_targets_[IPC_CREATEEVENT_TAG]; 1.142 + delete ipc_targets_[IPC_NTCREATEKEY_TAG]; 1.143 + delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG]; 1.144 + delete policy_maker_; 1.145 + delete policy_; 1.146 + ::DeleteCriticalSection(&lock_); 1.147 +} 1.148 + 1.149 +void PolicyBase::AddRef() { 1.150 + ::InterlockedIncrement(&ref_count); 1.151 +} 1.152 + 1.153 +void PolicyBase::Release() { 1.154 + if (0 == ::InterlockedDecrement(&ref_count)) 1.155 + delete this; 1.156 +} 1.157 + 1.158 +ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) { 1.159 + if (initial < lockdown) { 1.160 + return SBOX_ERROR_BAD_PARAMS; 1.161 + } 1.162 + initial_level_ = initial; 1.163 + lockdown_level_ = lockdown; 1.164 + return SBOX_ALL_OK; 1.165 +} 1.166 + 1.167 +ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) { 1.168 + job_level_ = job_level; 1.169 + ui_exceptions_ = ui_exceptions; 1.170 + return SBOX_ALL_OK; 1.171 +} 1.172 + 1.173 +ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) { 1.174 + use_alternate_desktop_ = true; 1.175 + use_alternate_winstation_ = alternate_winstation; 1.176 + return CreateAlternateDesktop(alternate_winstation); 1.177 +} 1.178 + 1.179 +string16 PolicyBase::GetAlternateDesktop() const { 1.180 + // No alternate desktop or winstation. Return an empty string. 1.181 + if (!use_alternate_desktop_ && !use_alternate_winstation_) { 1.182 + return string16(); 1.183 + } 1.184 + 1.185 + // The desktop and winstation should have been created by now. 1.186 + // If we hit this scenario, it means that the user ignored the failure 1.187 + // during SetAlternateDesktop, so we ignore it here too. 1.188 + if (use_alternate_desktop_ && !alternate_desktop_handle_) { 1.189 + return string16(); 1.190 + } 1.191 + if (use_alternate_winstation_ && (!alternate_desktop_handle_ || 1.192 + !alternate_winstation_handle_)) { 1.193 + return string16(); 1.194 + } 1.195 + 1.196 + return GetFullDesktopName(alternate_winstation_handle_, 1.197 + alternate_desktop_handle_); 1.198 +} 1.199 + 1.200 +ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) { 1.201 + if (alternate_winstation) { 1.202 + // Previously called with alternate_winstation = false? 1.203 + if (!alternate_winstation_handle_ && alternate_desktop_handle_) 1.204 + return SBOX_ERROR_UNSUPPORTED; 1.205 + 1.206 + // Check if it's already created. 1.207 + if (alternate_winstation_handle_ && alternate_desktop_handle_) 1.208 + return SBOX_ALL_OK; 1.209 + 1.210 + DCHECK(!alternate_winstation_handle_); 1.211 + // Create the window station. 1.212 + ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_); 1.213 + if (SBOX_ALL_OK != result) 1.214 + return result; 1.215 + 1.216 + // Verify that everything is fine. 1.217 + if (!alternate_winstation_handle_ || 1.218 + GetWindowObjectName(alternate_winstation_handle_).empty()) 1.219 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.220 + 1.221 + // Create the destkop. 1.222 + result = CreateAltDesktop(alternate_winstation_handle_, 1.223 + &alternate_desktop_handle_); 1.224 + if (SBOX_ALL_OK != result) 1.225 + return result; 1.226 + 1.227 + // Verify that everything is fine. 1.228 + if (!alternate_desktop_handle_ || 1.229 + GetWindowObjectName(alternate_desktop_handle_).empty()) 1.230 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.231 + } else { 1.232 + // Previously called with alternate_winstation = true? 1.233 + if (alternate_winstation_handle_) 1.234 + return SBOX_ERROR_UNSUPPORTED; 1.235 + 1.236 + // Check if it already exists. 1.237 + if (alternate_desktop_handle_) 1.238 + return SBOX_ALL_OK; 1.239 + 1.240 + // Create the destkop. 1.241 + ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_); 1.242 + if (SBOX_ALL_OK != result) 1.243 + return result; 1.244 + 1.245 + // Verify that everything is fine. 1.246 + if (!alternate_desktop_handle_ || 1.247 + GetWindowObjectName(alternate_desktop_handle_).empty()) 1.248 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.249 + } 1.250 + 1.251 + return SBOX_ALL_OK; 1.252 +} 1.253 + 1.254 +void PolicyBase::DestroyAlternateDesktop() { 1.255 + if (alternate_desktop_handle_) { 1.256 + ::CloseDesktop(alternate_desktop_handle_); 1.257 + alternate_desktop_handle_ = NULL; 1.258 + } 1.259 + 1.260 + if (alternate_winstation_handle_) { 1.261 + ::CloseWindowStation(alternate_winstation_handle_); 1.262 + alternate_winstation_handle_ = NULL; 1.263 + } 1.264 +} 1.265 + 1.266 +ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) { 1.267 + integrity_level_ = integrity_level; 1.268 + return SBOX_ALL_OK; 1.269 +} 1.270 + 1.271 +ResultCode PolicyBase::SetDelayedIntegrityLevel( 1.272 + IntegrityLevel integrity_level) { 1.273 + delayed_integrity_level_ = integrity_level; 1.274 + return SBOX_ALL_OK; 1.275 +} 1.276 + 1.277 +ResultCode PolicyBase::SetAppContainer(const wchar_t* sid) { 1.278 + if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) 1.279 + return SBOX_ALL_OK; 1.280 + 1.281 + // Windows refuses to work with an impersonation token for a process inside 1.282 + // an AppContainer. If the caller wants to use a more privileged initial 1.283 + // token, or if the lockdown level will prevent the process from starting, 1.284 + // we have to fail the operation. 1.285 + if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) 1.286 + return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; 1.287 + 1.288 + DCHECK(!appcontainer_list_.get()); 1.289 + appcontainer_list_.reset(new AppContainerAttributes); 1.290 + ResultCode rv = appcontainer_list_->SetAppContainer(sid, capabilities_); 1.291 + if (rv != SBOX_ALL_OK) 1.292 + return rv; 1.293 + 1.294 + return SBOX_ALL_OK; 1.295 +} 1.296 + 1.297 +ResultCode PolicyBase::SetCapability(const wchar_t* sid) { 1.298 + capabilities_.push_back(sid); 1.299 + return SBOX_ALL_OK; 1.300 +} 1.301 + 1.302 +ResultCode PolicyBase::SetProcessMitigations( 1.303 + MitigationFlags flags) { 1.304 + if (!CanSetProcessMitigationsPreStartup(flags)) 1.305 + return SBOX_ERROR_BAD_PARAMS; 1.306 + mitigations_ = flags; 1.307 + return SBOX_ALL_OK; 1.308 +} 1.309 + 1.310 +MitigationFlags PolicyBase::GetProcessMitigations() { 1.311 + return mitigations_; 1.312 +} 1.313 + 1.314 +ResultCode PolicyBase::SetDelayedProcessMitigations( 1.315 + MitigationFlags flags) { 1.316 + if (!CanSetProcessMitigationsPostStartup(flags)) 1.317 + return SBOX_ERROR_BAD_PARAMS; 1.318 + delayed_mitigations_ = flags; 1.319 + return SBOX_ALL_OK; 1.320 +} 1.321 + 1.322 +MitigationFlags PolicyBase::GetDelayedProcessMitigations() { 1.323 + return delayed_mitigations_; 1.324 +} 1.325 + 1.326 +void PolicyBase::SetStrictInterceptions() { 1.327 + relaxed_interceptions_ = false; 1.328 +} 1.329 + 1.330 +ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) { 1.331 + if (!IsInheritableHandle(handle)) 1.332 + return SBOX_ERROR_BAD_PARAMS; 1.333 + stdout_handle_ = handle; 1.334 + return SBOX_ALL_OK; 1.335 +} 1.336 + 1.337 +ResultCode PolicyBase::SetStderrHandle(HANDLE handle) { 1.338 + if (!IsInheritableHandle(handle)) 1.339 + return SBOX_ERROR_BAD_PARAMS; 1.340 + stderr_handle_ = handle; 1.341 + return SBOX_ALL_OK; 1.342 +} 1.343 + 1.344 +ResultCode PolicyBase::AddRule(SubSystem subsystem, Semantics semantics, 1.345 + const wchar_t* pattern) { 1.346 + if (NULL == policy_) { 1.347 + policy_ = MakeBrokerPolicyMemory(); 1.348 + DCHECK(policy_); 1.349 + policy_maker_ = new LowLevelPolicy(policy_); 1.350 + DCHECK(policy_maker_); 1.351 + } 1.352 + 1.353 + switch (subsystem) { 1.354 + case SUBSYS_FILES: { 1.355 + if (!file_system_init_) { 1.356 + if (!FileSystemPolicy::SetInitialRules(policy_maker_)) 1.357 + return SBOX_ERROR_BAD_PARAMS; 1.358 + file_system_init_ = true; 1.359 + } 1.360 + if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.361 + NOTREACHED(); 1.362 + return SBOX_ERROR_BAD_PARAMS; 1.363 + } 1.364 + break; 1.365 + } 1.366 + case SUBSYS_SYNC: { 1.367 + if (!SyncPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.368 + NOTREACHED(); 1.369 + return SBOX_ERROR_BAD_PARAMS; 1.370 + } 1.371 + break; 1.372 + } 1.373 + case SUBSYS_PROCESS: { 1.374 + if (lockdown_level_ < USER_INTERACTIVE && 1.375 + TargetPolicy::PROCESS_ALL_EXEC == semantics) { 1.376 + // This is unsupported. This is a huge security risk to give full access 1.377 + // to a process handle. 1.378 + return SBOX_ERROR_UNSUPPORTED; 1.379 + } 1.380 + if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.381 + NOTREACHED(); 1.382 + return SBOX_ERROR_BAD_PARAMS; 1.383 + } 1.384 + break; 1.385 + } 1.386 + case SUBSYS_NAMED_PIPES: { 1.387 + if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.388 + NOTREACHED(); 1.389 + return SBOX_ERROR_BAD_PARAMS; 1.390 + } 1.391 + break; 1.392 + } 1.393 + case SUBSYS_REGISTRY: { 1.394 + if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.395 + NOTREACHED(); 1.396 + return SBOX_ERROR_BAD_PARAMS; 1.397 + } 1.398 + break; 1.399 + } 1.400 + case SUBSYS_HANDLES: { 1.401 + if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) { 1.402 + NOTREACHED(); 1.403 + return SBOX_ERROR_BAD_PARAMS; 1.404 + } 1.405 + break; 1.406 + } 1.407 + default: { 1.408 + return SBOX_ERROR_UNSUPPORTED; 1.409 + } 1.410 + } 1.411 + 1.412 + return SBOX_ALL_OK; 1.413 +} 1.414 + 1.415 +ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) { 1.416 + blacklisted_dlls_.push_back(dll_name); 1.417 + return SBOX_ALL_OK; 1.418 +} 1.419 + 1.420 +ResultCode PolicyBase::AddKernelObjectToClose(const char16* handle_type, 1.421 + const char16* handle_name) { 1.422 + return handle_closer_.AddHandle(handle_type, handle_name); 1.423 +} 1.424 + 1.425 +// When an IPC is ready in any of the targets we get called. We manage an array 1.426 +// of IPC dispatchers which are keyed on the IPC tag so we normally delegate 1.427 +// to the appropriate dispatcher unless we can handle the IPC call ourselves. 1.428 +Dispatcher* PolicyBase::OnMessageReady(IPCParams* ipc, 1.429 + CallbackGeneric* callback) { 1.430 + DCHECK(callback); 1.431 + static const IPCParams ping1 = {IPC_PING1_TAG, ULONG_TYPE}; 1.432 + static const IPCParams ping2 = {IPC_PING2_TAG, INOUTPTR_TYPE}; 1.433 + 1.434 + if (ping1.Matches(ipc) || ping2.Matches(ipc)) { 1.435 + *callback = reinterpret_cast<CallbackGeneric>( 1.436 + static_cast<Callback1>(&PolicyBase::Ping)); 1.437 + return this; 1.438 + } 1.439 + 1.440 + Dispatcher* dispatch = GetDispatcher(ipc->ipc_tag); 1.441 + if (!dispatch) { 1.442 + NOTREACHED(); 1.443 + return NULL; 1.444 + } 1.445 + return dispatch->OnMessageReady(ipc, callback); 1.446 +} 1.447 + 1.448 +// Delegate to the appropriate dispatcher. 1.449 +bool PolicyBase::SetupService(InterceptionManager* manager, int service) { 1.450 + if (IPC_PING1_TAG == service || IPC_PING2_TAG == service) 1.451 + return true; 1.452 + 1.453 + Dispatcher* dispatch = GetDispatcher(service); 1.454 + if (!dispatch) { 1.455 + NOTREACHED(); 1.456 + return false; 1.457 + } 1.458 + return dispatch->SetupService(manager, service); 1.459 +} 1.460 + 1.461 +ResultCode PolicyBase::MakeJobObject(HANDLE* job) { 1.462 + if (job_level_ != JOB_NONE) { 1.463 + // Create the windows job object. 1.464 + Job job_obj; 1.465 + DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_); 1.466 + if (ERROR_SUCCESS != result) { 1.467 + return SBOX_ERROR_GENERIC; 1.468 + } 1.469 + *job = job_obj.Detach(); 1.470 + } else { 1.471 + *job = NULL; 1.472 + } 1.473 + return SBOX_ALL_OK; 1.474 +} 1.475 + 1.476 +ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { 1.477 + // Create the 'naked' token. This will be the permanent token associated 1.478 + // with the process and therefore with any thread that is not impersonating. 1.479 + DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, 1.480 + integrity_level_, PRIMARY); 1.481 + if (ERROR_SUCCESS != result) { 1.482 + return SBOX_ERROR_GENERIC; 1.483 + } 1.484 + 1.485 + if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { 1.486 + // Windows refuses to work with an impersonation token. See SetAppContainer 1.487 + // implementation for more details. 1.488 + if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) 1.489 + return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; 1.490 + 1.491 + *initial = INVALID_HANDLE_VALUE; 1.492 + return SBOX_ALL_OK; 1.493 + } 1.494 + 1.495 + // Create the 'better' token. We use this token as the one that the main 1.496 + // thread uses when booting up the process. It should contain most of 1.497 + // what we need (before reaching main( )) 1.498 + result = CreateRestrictedToken(initial, initial_level_, 1.499 + integrity_level_, IMPERSONATION); 1.500 + if (ERROR_SUCCESS != result) { 1.501 + ::CloseHandle(*lockdown); 1.502 + return SBOX_ERROR_GENERIC; 1.503 + } 1.504 + return SBOX_ALL_OK; 1.505 +} 1.506 + 1.507 +const AppContainerAttributes* PolicyBase::GetAppContainer() { 1.508 + if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) 1.509 + return NULL; 1.510 + 1.511 + return appcontainer_list_.get(); 1.512 +} 1.513 + 1.514 +bool PolicyBase::AddTarget(TargetProcess* target) { 1.515 + if (NULL != policy_) 1.516 + policy_maker_->Done(); 1.517 + 1.518 + if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), 1.519 + mitigations_)) { 1.520 + return false; 1.521 + } 1.522 + 1.523 + if (!SetupAllInterceptions(target)) 1.524 + return false; 1.525 + 1.526 + if (!SetupHandleCloser(target)) 1.527 + return false; 1.528 + 1.529 + // Initialize the sandbox infrastructure for the target. 1.530 + if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize)) 1.531 + return false; 1.532 + 1.533 + g_shared_delayed_integrity_level = delayed_integrity_level_; 1.534 + ResultCode ret = target->TransferVariable( 1.535 + "g_shared_delayed_integrity_level", 1.536 + &g_shared_delayed_integrity_level, 1.537 + sizeof(g_shared_delayed_integrity_level)); 1.538 + g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; 1.539 + if (SBOX_ALL_OK != ret) 1.540 + return false; 1.541 + 1.542 + // Add in delayed mitigations and pseudo-mitigations enforced at startup. 1.543 + g_shared_delayed_mitigations = delayed_mitigations_ | 1.544 + FilterPostStartupProcessMitigations(mitigations_); 1.545 + if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations)) 1.546 + return false; 1.547 + 1.548 + ret = target->TransferVariable("g_shared_delayed_mitigations", 1.549 + &g_shared_delayed_mitigations, 1.550 + sizeof(g_shared_delayed_mitigations)); 1.551 + g_shared_delayed_mitigations = 0; 1.552 + if (SBOX_ALL_OK != ret) 1.553 + return false; 1.554 + 1.555 + AutoLock lock(&lock_); 1.556 + targets_.push_back(target); 1.557 + return true; 1.558 +} 1.559 + 1.560 +bool PolicyBase::OnJobEmpty(HANDLE job) { 1.561 + AutoLock lock(&lock_); 1.562 + TargetSet::iterator it; 1.563 + for (it = targets_.begin(); it != targets_.end(); ++it) { 1.564 + if ((*it)->Job() == job) 1.565 + break; 1.566 + } 1.567 + if (it == targets_.end()) { 1.568 + return false; 1.569 + } 1.570 + TargetProcess* target = *it; 1.571 + targets_.erase(it); 1.572 + delete target; 1.573 + return true; 1.574 +} 1.575 + 1.576 +EvalResult PolicyBase::EvalPolicy(int service, 1.577 + CountedParameterSetBase* params) { 1.578 + if (NULL != policy_) { 1.579 + if (NULL == policy_->entry[service]) { 1.580 + // There is no policy for this particular service. This is not a big 1.581 + // deal. 1.582 + return DENY_ACCESS; 1.583 + } 1.584 + for (int i = 0; i < params->count; i++) { 1.585 + if (!params->parameters[i].IsValid()) { 1.586 + NOTREACHED(); 1.587 + return SIGNAL_ALARM; 1.588 + } 1.589 + } 1.590 + PolicyProcessor pol_evaluator(policy_->entry[service]); 1.591 + PolicyResult result = pol_evaluator.Evaluate(kShortEval, 1.592 + params->parameters, 1.593 + params->count); 1.594 + if (POLICY_MATCH == result) { 1.595 + return pol_evaluator.GetAction(); 1.596 + } 1.597 + DCHECK(POLICY_ERROR != result); 1.598 + } 1.599 + 1.600 + return DENY_ACCESS; 1.601 +} 1.602 + 1.603 +HANDLE PolicyBase::GetStdoutHandle() { 1.604 + return stdout_handle_; 1.605 +} 1.606 + 1.607 +HANDLE PolicyBase::GetStderrHandle() { 1.608 + return stderr_handle_; 1.609 +} 1.610 + 1.611 +// We service IPC_PING_TAG message which is a way to test a round trip of the 1.612 +// IPC subsystem. We receive a integer cookie and we are expected to return the 1.613 +// cookie times two (or three) and the current tick count. 1.614 +bool PolicyBase::Ping(IPCInfo* ipc, void* arg1) { 1.615 + switch (ipc->ipc_tag) { 1.616 + case IPC_PING1_TAG: { 1.617 + IPCInt ipc_int(arg1); 1.618 + uint32 cookie = ipc_int.As32Bit(); 1.619 + ipc->return_info.extended_count = 2; 1.620 + ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); 1.621 + ipc->return_info.extended[1].unsigned_int = 2 * cookie; 1.622 + return true; 1.623 + } 1.624 + case IPC_PING2_TAG: { 1.625 + CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); 1.626 + if (sizeof(uint32) != io_buffer->Size()) 1.627 + return false; 1.628 + 1.629 + uint32* cookie = reinterpret_cast<uint32*>(io_buffer->Buffer()); 1.630 + *cookie = (*cookie) * 3; 1.631 + return true; 1.632 + } 1.633 + default: return false; 1.634 + } 1.635 +} 1.636 + 1.637 +Dispatcher* PolicyBase::GetDispatcher(int ipc_tag) { 1.638 + if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG) 1.639 + return NULL; 1.640 + 1.641 + return ipc_targets_[ipc_tag]; 1.642 +} 1.643 + 1.644 +bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { 1.645 + InterceptionManager manager(target, relaxed_interceptions_); 1.646 + 1.647 + if (policy_) { 1.648 + for (int i = 0; i < IPC_LAST_TAG; i++) { 1.649 + if (policy_->entry[i] && !ipc_targets_[i]->SetupService(&manager, i)) 1.650 + return false; 1.651 + } 1.652 + } 1.653 + 1.654 + if (!blacklisted_dlls_.empty()) { 1.655 + std::vector<string16>::iterator it = blacklisted_dlls_.begin(); 1.656 + for (; it != blacklisted_dlls_.end(); ++it) { 1.657 + manager.AddToUnloadModules(it->c_str()); 1.658 + } 1.659 + } 1.660 + 1.661 + if (!handle_closer_.SetupHandleInterceptions(&manager)) 1.662 + return false; 1.663 + 1.664 + if (!SetupBasicInterceptions(&manager)) 1.665 + return false; 1.666 + 1.667 + if (!manager.InitializeInterceptions()) 1.668 + return false; 1.669 + 1.670 + // Finally, setup imports on the target so the interceptions can work. 1.671 + return SetupNtdllImports(target); 1.672 +} 1.673 + 1.674 +bool PolicyBase::SetupHandleCloser(TargetProcess* target) { 1.675 + return handle_closer_.InitializeTargetHandles(target); 1.676 +} 1.677 + 1.678 +} // namespace sandbox