// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/sandbox_policy_base.h"

#include <sddl.h>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/app_container.h"
#include "sandbox/win/src/filesystem_dispatcher.h"
#include "sandbox/win/src/filesystem_policy.h"
#include "sandbox/win/src/handle_dispatcher.h"
#include "sandbox/win/src/handle_policy.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/named_pipe_dispatcher.h"
#include "sandbox/win/src/named_pipe_policy.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_engine_processor.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
#include "sandbox/win/src/process_mitigations_win32k_policy.h"
#include "sandbox/win/src/process_thread_dispatcher.h"
#include "sandbox/win/src/process_thread_policy.h"
#include "sandbox/win/src/registry_dispatcher.h"
#include "sandbox/win/src/registry_policy.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sync_dispatcher.h"
#include "sandbox/win/src/sync_policy.h"
#include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/window.h"

namespace {

// The standard windows size for one memory page.
const size_t kOneMemPage = 4096;
// The IPC and Policy shared memory sizes.
const size_t kIPCMemSize = kOneMemPage * 2;
const size_t kPolMemSize = kOneMemPage * 14;

// Helper function to allocate space (on the heap) for policy.
sandbox::PolicyGlobal* MakeBrokerPolicyMemory() {
  const size_t kTotalPolicySz = kPolMemSize;
  sandbox::PolicyGlobal* policy = static_cast<sandbox::PolicyGlobal*>
      (::operator new(kTotalPolicySz));
  DCHECK(policy);
  memset(policy, 0, kTotalPolicySz);
  policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal);
  return policy;
}

bool IsInheritableHandle(HANDLE handle) {
  if (!handle)
    return false;
  if (handle == INVALID_HANDLE_VALUE)
    return false;
  // File handles (FILE_TYPE_DISK) and pipe handles are known to be
  // inheritable.  Console handles (FILE_TYPE_CHAR) are not
  // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
  DWORD handle_type = GetFileType(handle);
  return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE;
}

}

namespace sandbox {

SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level;
SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations;

// Initializes static members.
HWINSTA PolicyBase::alternate_winstation_handle_ = NULL;
HDESK PolicyBase::alternate_desktop_handle_ = NULL;
IntegrityLevel PolicyBase::alternate_desktop_integrity_level_label_ =
    INTEGRITY_LEVEL_SYSTEM;

PolicyBase::PolicyBase()
    : ref_count(1),
      lockdown_level_(USER_LOCKDOWN),
      initial_level_(USER_LOCKDOWN),
      job_level_(JOB_LOCKDOWN),
      ui_exceptions_(0),
      memory_limit_(0),
      use_alternate_desktop_(false),
      use_alternate_winstation_(false),
      file_system_init_(false),
      relaxed_interceptions_(true),
      stdout_handle_(INVALID_HANDLE_VALUE),
      stderr_handle_(INVALID_HANDLE_VALUE),
      integrity_level_(INTEGRITY_LEVEL_LAST),
      delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
      mitigations_(0),
      delayed_mitigations_(0),
      policy_maker_(NULL),
      policy_(NULL) {
  ::InitializeCriticalSection(&lock_);
  // Initialize the IPC dispatcher array.
  memset(&ipc_targets_, NULL, sizeof(ipc_targets_));
  Dispatcher* dispatcher = NULL;

  dispatcher = new FilesystemDispatcher(this);
  ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher;
  ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher;

  dispatcher = new NamedPipeDispatcher(this);
  ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher;

  dispatcher = new ThreadProcessDispatcher(this);
  ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher;
  ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher;

  dispatcher = new SyncDispatcher(this);
  ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher;
  ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher;

  dispatcher = new RegistryDispatcher(this);
  ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher;

  dispatcher = new HandleDispatcher(this);
  ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher;

  dispatcher = new ProcessMitigationsWin32KDispatcher(this);
  ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher;
  ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher;
  ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher;
}

PolicyBase::~PolicyBase() {
  TargetSet::iterator it;
  for (it = targets_.begin(); it != targets_.end(); ++it) {
    TargetProcess* target = (*it);
    delete target;
  }
  delete ipc_targets_[IPC_NTCREATEFILE_TAG];
  delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG];
  delete ipc_targets_[IPC_NTOPENTHREAD_TAG];
  delete ipc_targets_[IPC_CREATEEVENT_TAG];
  delete ipc_targets_[IPC_NTCREATEKEY_TAG];
  delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG];
  delete policy_maker_;
  delete policy_;
  ::DeleteCriticalSection(&lock_);
}

void PolicyBase::AddRef() {
  ::InterlockedIncrement(&ref_count);
}

void PolicyBase::Release() {
  if (0 == ::InterlockedDecrement(&ref_count))
    delete this;
}

ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) {
  if (initial < lockdown) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  initial_level_ = initial;
  lockdown_level_ = lockdown;
  return SBOX_ALL_OK;
}

TokenLevel PolicyBase::GetInitialTokenLevel() const {
  return initial_level_;
}

TokenLevel PolicyBase::GetLockdownTokenLevel() const{
  return lockdown_level_;
}

ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) {
  if (memory_limit_ && job_level == JOB_NONE) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  job_level_ = job_level;
  ui_exceptions_ = ui_exceptions;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetJobMemoryLimit(size_t memory_limit) {
  if (memory_limit && job_level_ == JOB_NONE) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  memory_limit_ = memory_limit;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) {
  use_alternate_desktop_ = true;
  use_alternate_winstation_ = alternate_winstation;
  return CreateAlternateDesktop(alternate_winstation);
}

base::string16 PolicyBase::GetAlternateDesktop() const {
  // No alternate desktop or winstation. Return an empty string.
  if (!use_alternate_desktop_ && !use_alternate_winstation_) {
    return base::string16();
  }

  // The desktop and winstation should have been created by now.
  // If we hit this scenario, it means that the user ignored the failure
  // during SetAlternateDesktop, so we ignore it here too.
  if (use_alternate_desktop_ && !alternate_desktop_handle_) {
    return base::string16();
  }
  if (use_alternate_winstation_ && (!alternate_desktop_handle_ ||
                                    !alternate_winstation_handle_)) {
    return base::string16();
  }

  return GetFullDesktopName(alternate_winstation_handle_,
                            alternate_desktop_handle_);
}

ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) {
  if (alternate_winstation) {
    // Previously called with alternate_winstation = false?
    if (!alternate_winstation_handle_ && alternate_desktop_handle_)
      return SBOX_ERROR_UNSUPPORTED;

    // Check if it's already created.
    if (alternate_winstation_handle_ && alternate_desktop_handle_)
      return SBOX_ALL_OK;

    DCHECK(!alternate_winstation_handle_);
    // Create the window station.
    ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_winstation_handle_ ||
        GetWindowObjectName(alternate_winstation_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;

    // Create the destkop.
    result = CreateAltDesktop(alternate_winstation_handle_,
                              &alternate_desktop_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_desktop_handle_ ||
        GetWindowObjectName(alternate_desktop_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
  } else {
    // Previously called with alternate_winstation = true?
    if (alternate_winstation_handle_)
      return SBOX_ERROR_UNSUPPORTED;

    // Check if it already exists.
    if (alternate_desktop_handle_)
      return SBOX_ALL_OK;

    // Create the destkop.
    ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_desktop_handle_ ||
        GetWindowObjectName(alternate_desktop_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
  }

  return SBOX_ALL_OK;
}

void PolicyBase::DestroyAlternateDesktop() {
  if (alternate_desktop_handle_) {
    ::CloseDesktop(alternate_desktop_handle_);
    alternate_desktop_handle_ = NULL;
  }

  if (alternate_winstation_handle_) {
    ::CloseWindowStation(alternate_winstation_handle_);
    alternate_winstation_handle_ = NULL;
  }
}

ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) {
  integrity_level_ = integrity_level;
  return SBOX_ALL_OK;
}

IntegrityLevel PolicyBase::GetIntegrityLevel() const {
  return integrity_level_;
}

ResultCode PolicyBase::SetDelayedIntegrityLevel(
    IntegrityLevel integrity_level) {
  delayed_integrity_level_ = integrity_level;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetAppContainer(const wchar_t* sid) {
  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
    return SBOX_ALL_OK;

  // Windows refuses to work with an impersonation token for a process inside
  // an AppContainer. If the caller wants to use a more privileged initial
  // token, or if the lockdown level will prevent the process from starting,
  // we have to fail the operation.
  if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_)
    return SBOX_ERROR_CANNOT_INIT_APPCONTAINER;

  DCHECK(!appcontainer_list_.get());
  appcontainer_list_.reset(new AppContainerAttributes);
  ResultCode rv = appcontainer_list_->SetAppContainer(sid, capabilities_);
  if (rv != SBOX_ALL_OK)
    return rv;

  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetCapability(const wchar_t* sid) {
  capabilities_.push_back(sid);
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetProcessMitigations(
    MitigationFlags flags) {
  if (!CanSetProcessMitigationsPreStartup(flags))
    return SBOX_ERROR_BAD_PARAMS;
  mitigations_ = flags;
  return SBOX_ALL_OK;
}

MitigationFlags PolicyBase::GetProcessMitigations() {
  return mitigations_;
}

ResultCode PolicyBase::SetDelayedProcessMitigations(
    MitigationFlags flags) {
  if (!CanSetProcessMitigationsPostStartup(flags))
    return SBOX_ERROR_BAD_PARAMS;
  delayed_mitigations_ = flags;
  return SBOX_ALL_OK;
}

MitigationFlags PolicyBase::GetDelayedProcessMitigations() const {
  return delayed_mitigations_;
}

void PolicyBase::SetStrictInterceptions() {
  relaxed_interceptions_ = false;
}

ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) {
  if (!IsInheritableHandle(handle))
    return SBOX_ERROR_BAD_PARAMS;
  stdout_handle_ = handle;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetStderrHandle(HANDLE handle) {
  if (!IsInheritableHandle(handle))
    return SBOX_ERROR_BAD_PARAMS;
  stderr_handle_ = handle;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::AddRule(SubSystem subsystem,
                               Semantics semantics,
                               const wchar_t* pattern) {
  ResultCode result = AddRuleInternal(subsystem, semantics, pattern);
  LOG_IF(ERROR, result != SBOX_ALL_OK) << "Failed to add sandbox rule."
                                       << " error = " << result
                                       << ", subsystem = " << subsystem
                                       << ", semantics = " << semantics
                                       << ", pattern = '" << pattern << "'";
  return result;
}

ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) {
  blacklisted_dlls_.push_back(dll_name);
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::AddKernelObjectToClose(const base::char16* handle_type,
                                              const base::char16* handle_name) {
  return handle_closer_.AddHandle(handle_type, handle_name);
}

// When an IPC is ready in any of the targets we get called. We manage an array
// of IPC dispatchers which are keyed on the IPC tag so we normally delegate
// to the appropriate dispatcher unless we can handle the IPC call ourselves.
Dispatcher* PolicyBase::OnMessageReady(IPCParams* ipc,
                                       CallbackGeneric* callback) {
  DCHECK(callback);
  static const IPCParams ping1 = {IPC_PING1_TAG, ULONG_TYPE};
  static const IPCParams ping2 = {IPC_PING2_TAG, INOUTPTR_TYPE};

  if (ping1.Matches(ipc) || ping2.Matches(ipc)) {
    *callback = reinterpret_cast<CallbackGeneric>(
                    static_cast<Callback1>(&PolicyBase::Ping));
    return this;
  }

  Dispatcher* dispatch = GetDispatcher(ipc->ipc_tag);
  if (!dispatch) {
    NOTREACHED();
    return NULL;
  }
  return dispatch->OnMessageReady(ipc, callback);
}

// Delegate to the appropriate dispatcher.
bool PolicyBase::SetupService(InterceptionManager* manager, int service) {
  if (IPC_PING1_TAG == service || IPC_PING2_TAG == service)
    return true;

  Dispatcher* dispatch = GetDispatcher(service);
  if (!dispatch) {
    NOTREACHED();
    return false;
  }
  return dispatch->SetupService(manager, service);
}

ResultCode PolicyBase::MakeJobObject(HANDLE* job) {
  if (job_level_ != JOB_NONE) {
    // Create the windows job object.
    Job job_obj;
    DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_,
                                memory_limit_);
    if (ERROR_SUCCESS != result) {
      return SBOX_ERROR_GENERIC;
    }
    *job = job_obj.Detach();
  } else {
    *job = NULL;
  }
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) {
  // Create the 'naked' token. This will be the permanent token associated
  // with the process and therefore with any thread that is not impersonating.
  DWORD result = CreateRestrictedToken(lockdown, lockdown_level_,
                                       integrity_level_, PRIMARY);
  if (ERROR_SUCCESS != result)
    return SBOX_ERROR_GENERIC;

  // If we're launching on the alternate desktop we need to make sure the
  // integrity label on the object is no higher than the sandboxed process's
  // integrity level. So, we lower the label on the desktop process if it's
  // not already low enough for our process.
  if (alternate_desktop_handle_ && use_alternate_desktop_ &&
      integrity_level_ != INTEGRITY_LEVEL_LAST &&
      alternate_desktop_integrity_level_label_ < integrity_level_ &&
      base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
    // Integrity label enum is reversed (higher level is a lower value).
    static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED,
                  "Integrity level ordering reversed.");
    result = SetObjectIntegrityLabel(alternate_desktop_handle_,
                                     SE_WINDOW_OBJECT,
                                     L"",
                                     GetIntegrityLevelString(integrity_level_));
    if (ERROR_SUCCESS != result)
      return SBOX_ERROR_GENERIC;

    alternate_desktop_integrity_level_label_ = integrity_level_;
  }

  if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) {
    // Windows refuses to work with an impersonation token. See SetAppContainer
    // implementation for more details.
    if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_)
      return SBOX_ERROR_CANNOT_INIT_APPCONTAINER;

    *initial = INVALID_HANDLE_VALUE;
    return SBOX_ALL_OK;
  }

  // Create the 'better' token. We use this token as the one that the main
  // thread uses when booting up the process. It should contain most of
  // what we need (before reaching main( ))
  result = CreateRestrictedToken(initial, initial_level_,
                                 integrity_level_, IMPERSONATION);
  if (ERROR_SUCCESS != result) {
    ::CloseHandle(*lockdown);
    return SBOX_ERROR_GENERIC;
  }
  return SBOX_ALL_OK;
}

const AppContainerAttributes* PolicyBase::GetAppContainer() {
  if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer())
    return NULL;

  return appcontainer_list_.get();
}

bool PolicyBase::AddTarget(TargetProcess* target) {
  if (NULL != policy_)
    policy_maker_->Done();

  if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(),
                                                 mitigations_)) {
    return false;
  }

  if (!SetupAllInterceptions(target))
    return false;

  if (!SetupHandleCloser(target))
    return false;

  // Initialize the sandbox infrastructure for the target.
  if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize))
    return false;

  g_shared_delayed_integrity_level = delayed_integrity_level_;
  ResultCode ret = target->TransferVariable(
                       "g_shared_delayed_integrity_level",
                       &g_shared_delayed_integrity_level,
                       sizeof(g_shared_delayed_integrity_level));
  g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST;
  if (SBOX_ALL_OK != ret)
    return false;

  // Add in delayed mitigations and pseudo-mitigations enforced at startup.
  g_shared_delayed_mitigations = delayed_mitigations_ |
      FilterPostStartupProcessMitigations(mitigations_);
  if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations))
    return false;

  ret = target->TransferVariable("g_shared_delayed_mitigations",
                                 &g_shared_delayed_mitigations,
                                 sizeof(g_shared_delayed_mitigations));
  g_shared_delayed_mitigations = 0;
  if (SBOX_ALL_OK != ret)
    return false;

  AutoLock lock(&lock_);
  targets_.push_back(target);
  return true;
}

bool PolicyBase::OnJobEmpty(HANDLE job) {
  AutoLock lock(&lock_);
  TargetSet::iterator it;
  for (it = targets_.begin(); it != targets_.end(); ++it) {
    if ((*it)->Job() == job)
      break;
  }
  if (it == targets_.end()) {
    return false;
  }
  TargetProcess* target = *it;
  targets_.erase(it);
  delete target;
  return true;
}

EvalResult PolicyBase::EvalPolicy(int service,
                                  CountedParameterSetBase* params) {
  if (NULL != policy_) {
    if (NULL == policy_->entry[service]) {
      // There is no policy for this particular service. This is not a big
      // deal.
      return DENY_ACCESS;
    }
    for (int i = 0; i < params->count; i++) {
      if (!params->parameters[i].IsValid()) {
        NOTREACHED();
        return SIGNAL_ALARM;
      }
    }
    PolicyProcessor pol_evaluator(policy_->entry[service]);
    PolicyResult result =  pol_evaluator.Evaluate(kShortEval,
                                                  params->parameters,
                                                  params->count);
    if (POLICY_MATCH == result) {
      return pol_evaluator.GetAction();
    }
    DCHECK(POLICY_ERROR != result);
  }

  return DENY_ACCESS;
}

HANDLE PolicyBase::GetStdoutHandle() {
  return stdout_handle_;
}

HANDLE PolicyBase::GetStderrHandle() {
  return stderr_handle_;
}

// We service IPC_PING_TAG message which is a way to test a round trip of the
// IPC subsystem. We receive a integer cookie and we are expected to return the
// cookie times two (or three) and the current tick count.
bool PolicyBase::Ping(IPCInfo* ipc, void* arg1) {
  switch (ipc->ipc_tag) {
    case IPC_PING1_TAG: {
      IPCInt ipc_int(arg1);
      uint32 cookie = ipc_int.As32Bit();
      ipc->return_info.extended_count = 2;
      ipc->return_info.extended[0].unsigned_int = ::GetTickCount();
      ipc->return_info.extended[1].unsigned_int = 2 * cookie;
      return true;
    }
    case IPC_PING2_TAG: {
      CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1);
      if (sizeof(uint32) != io_buffer->Size())
        return false;

      uint32* cookie = reinterpret_cast<uint32*>(io_buffer->Buffer());
      *cookie = (*cookie) * 3;
      return true;
    }
    default: return false;
  }
}

Dispatcher* PolicyBase::GetDispatcher(int ipc_tag) {
  if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG)
    return NULL;

  return ipc_targets_[ipc_tag];
}

bool PolicyBase::SetupAllInterceptions(TargetProcess* target) {
  InterceptionManager manager(target, relaxed_interceptions_);

  if (policy_) {
    for (int i = 0; i < IPC_LAST_TAG; i++) {
      if (policy_->entry[i] && !ipc_targets_[i]->SetupService(&manager, i))
          return false;
    }
  }

  if (!blacklisted_dlls_.empty()) {
    std::vector<base::string16>::iterator it = blacklisted_dlls_.begin();
    for (; it != blacklisted_dlls_.end(); ++it) {
      manager.AddToUnloadModules(it->c_str());
    }
  }

  if (!SetupBasicInterceptions(&manager))
    return false;

  if (!manager.InitializeInterceptions())
    return false;

  // Finally, setup imports on the target so the interceptions can work.
  return SetupNtdllImports(target);
}

bool PolicyBase::SetupHandleCloser(TargetProcess* target) {
  return handle_closer_.InitializeTargetHandles(target);
}

ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
                                       Semantics semantics,
                                       const wchar_t* pattern) {
  if (NULL == policy_) {
    policy_ = MakeBrokerPolicyMemory();
    DCHECK(policy_);
    policy_maker_ = new LowLevelPolicy(policy_);
    DCHECK(policy_maker_);
  }

  switch (subsystem) {
    case SUBSYS_FILES: {
      if (!file_system_init_) {
        if (!FileSystemPolicy::SetInitialRules(policy_maker_))
          return SBOX_ERROR_BAD_PARAMS;
        file_system_init_ = true;
      }
      if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_SYNC: {
      if (!SyncPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_PROCESS: {
      if (lockdown_level_ < USER_INTERACTIVE &&
          TargetPolicy::PROCESS_ALL_EXEC == semantics) {
        // This is unsupported. This is a huge security risk to give full access
        // to a process handle.
        return SBOX_ERROR_UNSUPPORTED;
      }
      if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_NAMED_PIPES: {
      if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_REGISTRY: {
      if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_HANDLES: {
      if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }

    case SUBSYS_WIN32K_LOCKDOWN: {
      if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
              pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }

    default: { return SBOX_ERROR_UNSUPPORTED; }
  }

  return SBOX_ALL_OK;
}

}  // namespace sandbox
