Home | History | Annotate | Download | only in src
      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