// 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/broker_services.h"

#include <AclAPI.h>

#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/threading/platform_thread.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_process_information.h"
#include "base/win/startup_information.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/app_container.h"
#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/win2k_threadpool.h"
#include "sandbox/win/src/win_utils.h"

namespace {

// Utility function to associate a completion port to a job object.
bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) {
  JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_acp = { key, port };
  return ::SetInformationJobObject(job,
                                   JobObjectAssociateCompletionPortInformation,
                                   &job_acp, sizeof(job_acp))? true : false;
}

// Utility function to do the cleanup necessary when something goes wrong
// while in SpawnTarget and we must terminate the target process.
sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target, DWORD error) {
  if (0 == error)
    error = ::GetLastError();

  target->Terminate();
  delete target;
  ::SetLastError(error);
  return sandbox::SBOX_ERROR_GENERIC;
}

// the different commands that you can send to the worker thread that
// executes TargetEventsThread().
enum {
  THREAD_CTRL_NONE,
  THREAD_CTRL_REMOVE_PEER,
  THREAD_CTRL_QUIT,
  THREAD_CTRL_LAST,
};

// Helper structure that allows the Broker to associate a job notification
// with a job object and with a policy.
struct JobTracker {
  JobTracker(base::win::ScopedHandle job, sandbox::PolicyBase* policy)
      : job(job.Pass()), policy(policy) {
  }
  ~JobTracker() {
    FreeResources();
  }

  // Releases the Job and notifies the associated Policy object to release its
  // resources as well.
  void FreeResources();

  base::win::ScopedHandle job;
  sandbox::PolicyBase* policy;
};

void JobTracker::FreeResources() {
  if (policy) {
    BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK);
    DCHECK(res);
    // Closing the job causes the target process to be destroyed so this needs
    // to happen before calling OnJobEmpty().
    HANDLE stale_job_handle = job.Get();
    job.Close();

    // In OnJobEmpty() we don't actually use the job handle directly.
    policy->OnJobEmpty(stale_job_handle);
    policy->Release();
    policy = NULL;
  }
}

// Helper structure that allows the broker to track peer processes
struct PeerTracker {
  PeerTracker(DWORD process_id, HANDLE broker_job_port)
      : wait_object(NULL), id(process_id), job_port(broker_job_port) {
  }

  HANDLE wait_object;
  base::win::ScopedHandle process;
  DWORD id;
  HANDLE job_port;
};

void DeregisterPeerTracker(PeerTracker* peer) {
  // Deregistration shouldn't fail, but we leak rather than crash if it does.
  if (::UnregisterWaitEx(peer->wait_object, INVALID_HANDLE_VALUE)) {
    delete peer;
  } else {
    NOTREACHED();
  }
}

}  // namespace

namespace sandbox {

BrokerServicesBase::BrokerServicesBase() : thread_pool_(NULL) {
}

// The broker uses a dedicated worker thread that services the job completion
// port to perform policy notifications and associated cleanup tasks.
ResultCode BrokerServicesBase::Init() {
  if (job_port_.IsValid() || (NULL != thread_pool_))
    return SBOX_ERROR_UNEXPECTED_CALL;

  ::InitializeCriticalSection(&lock_);

  job_port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0));
  if (!job_port_.IsValid())
    return SBOX_ERROR_GENERIC;

  no_targets_.Set(::CreateEventW(NULL, TRUE, FALSE, NULL));

  job_thread_.Set(::CreateThread(NULL, 0,  // Default security and stack.
                                 TargetEventsThread, this, NULL, NULL));
  if (!job_thread_.IsValid())
    return SBOX_ERROR_GENERIC;

  return SBOX_ALL_OK;
}

// The destructor should only be called when the Broker process is terminating.
// Since BrokerServicesBase is a singleton, this is called from the CRT
// termination handlers, if this code lives on a DLL it is called during
// DLL_PROCESS_DETACH in other words, holding the loader lock, so we cannot
// wait for threads here.
BrokerServicesBase::~BrokerServicesBase() {
  // If there is no port Init() was never called successfully.
  if (!job_port_.IsValid())
    return;

  // Closing the port causes, that no more Job notifications are delivered to
  // the worker thread and also causes the thread to exit. This is what we
  // want to do since we are going to close all outstanding Jobs and notifying
  // the policy objects ourselves.
  ::PostQueuedCompletionStatus(job_port_.Get(), 0, THREAD_CTRL_QUIT, FALSE);

  if (job_thread_.IsValid() &&
      WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_.Get(), 1000)) {
    // Cannot clean broker services.
    NOTREACHED();
    return;
  }

  STLDeleteElements(&tracker_list_);
  delete thread_pool_;

  // Cancel the wait events and delete remaining peer trackers.
  for (PeerTrackerMap::iterator it = peer_map_.begin();
       it != peer_map_.end(); ++it) {
    DeregisterPeerTracker(it->second);
  }

  ::DeleteCriticalSection(&lock_);
}

TargetPolicy* BrokerServicesBase::CreatePolicy() {
  // If you change the type of the object being created here you must also
  // change the downcast to it in SpawnTarget().
  return new PolicyBase;
}

// The worker thread stays in a loop waiting for asynchronous notifications
// from the job objects. Right now we only care about knowing when the last
// process on a job terminates, but in general this is the place to tell
// the policy about events.
DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) {
  if (NULL == param)
    return 1;

  base::PlatformThread::SetName("BrokerEvent");

  BrokerServicesBase* broker = reinterpret_cast<BrokerServicesBase*>(param);
  HANDLE port = broker->job_port_.Get();
  HANDLE no_targets = broker->no_targets_.Get();

  int target_counter = 0;
  ::ResetEvent(no_targets);

  while (true) {
    DWORD events = 0;
    ULONG_PTR key = 0;
    LPOVERLAPPED ovl = NULL;

    if (!::GetQueuedCompletionStatus(port, &events, &key, &ovl, INFINITE)) {
      // this call fails if the port has been closed before we have a
      // chance to service the last packet which is 'exit' anyway so
      // this is not an error.
      return 1;
    }

    if (key > THREAD_CTRL_LAST) {
      // The notification comes from a job object. There are nine notifications
      // that jobs can send and some of them depend on the job attributes set.
      JobTracker* tracker = reinterpret_cast<JobTracker*>(key);

      switch (events) {
        case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: {
          // The job object has signaled that the last process associated
          // with it has terminated. Assuming there is no way for a process
          // to appear out of thin air in this job, it safe to assume that
          // we can tell the policy to destroy the target object, and for
          // us to release our reference to the policy object.
          tracker->FreeResources();
          break;
        }

        case JOB_OBJECT_MSG_NEW_PROCESS: {
          ++target_counter;
          if (1 == target_counter) {
            ::ResetEvent(no_targets);
          }
          break;
        }

        case JOB_OBJECT_MSG_EXIT_PROCESS:
        case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
          {
            AutoLock lock(&broker->lock_);
            broker->child_process_ids_.erase(
                static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
          }
          --target_counter;
          if (0 == target_counter)
            ::SetEvent(no_targets);

          DCHECK(target_counter >= 0);
          break;
        }

        case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: {
          break;
        }

        case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
          BOOL res = ::TerminateJobObject(tracker->job.Get(),
                                          SBOX_FATAL_MEMORY_EXCEEDED);
          DCHECK(res);
          break;
        }

        default: {
          NOTREACHED();
          break;
        }
      }
    } else if (THREAD_CTRL_REMOVE_PEER == key) {
      // Remove a process from our list of peers.
      AutoLock lock(&broker->lock_);
      PeerTrackerMap::iterator it = broker->peer_map_.find(
          static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
      DeregisterPeerTracker(it->second);
      broker->peer_map_.erase(it);
    } else if (THREAD_CTRL_QUIT == key) {
      // The broker object is being destroyed so the thread needs to exit.
      return 0;
    } else {
      // We have not implemented more commands.
      NOTREACHED();
    }
  }

  NOTREACHED();
  return 0;
}

// SpawnTarget does all the interesting sandbox setup and creates the target
// process inside the sandbox.
ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
                                           const wchar_t* command_line,
                                           TargetPolicy* policy,
                                           PROCESS_INFORMATION* target_info) {
  if (!exe_path)
    return SBOX_ERROR_BAD_PARAMS;

  if (!policy)
    return SBOX_ERROR_BAD_PARAMS;

  // Even though the resources touched by SpawnTarget can be accessed in
  // multiple threads, the method itself cannot be called from more than
  // 1 thread. This is to protect the global variables used while setting up
  // the child process.
  static DWORD thread_id = ::GetCurrentThreadId();
  DCHECK(thread_id == ::GetCurrentThreadId());

  AutoLock lock(&lock_);

  // This downcast is safe as long as we control CreatePolicy()
  PolicyBase* policy_base = static_cast<PolicyBase*>(policy);

  if (policy_base->GetAppContainer() && policy_base->GetLowBoxSid())
    return SBOX_ERROR_BAD_PARAMS;

  // Construct the tokens and the job object that we are going to associate
  // with the soon to be created target process.
  base::win::ScopedHandle initial_token;
  base::win::ScopedHandle lockdown_token;
  base::win::ScopedHandle lowbox_token;
  ResultCode result = SBOX_ALL_OK;

  result =
      policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token);
  if (SBOX_ALL_OK != result)
    return result;

  base::win::ScopedHandle job;
  result = policy_base->MakeJobObject(&job);
  if (SBOX_ALL_OK != result)
    return result;

  // Initialize the startup information from the policy.
  base::win::StartupInformation startup_info;
  // The liftime of |mitigations| and |inherit_handle_list| have to be at least
  // as long as |startup_info| because |UpdateProcThreadAttribute| requires that
  // its |lpValue| parameter persist until |DeleteProcThreadAttributeList| is
  // called; StartupInformation's destructor makes such a call.
  DWORD64 mitigations;

  std::vector<HANDLE> inherited_handle_list;

  base::string16 desktop = policy_base->GetAlternateDesktop();
  if (!desktop.empty()) {
    startup_info.startup_info()->lpDesktop =
        const_cast<wchar_t*>(desktop.c_str());
  }

  bool inherit_handles = false;

  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
    int attribute_count = 0;
    const AppContainerAttributes* app_container =
        policy_base->GetAppContainer();
    if (app_container)
      ++attribute_count;

    size_t mitigations_size;
    ConvertProcessMitigationsToPolicy(policy->GetProcessMitigations(),
                                      &mitigations, &mitigations_size);
    if (mitigations)
      ++attribute_count;

    HANDLE stdout_handle = policy_base->GetStdoutHandle();
    HANDLE stderr_handle = policy_base->GetStderrHandle();

    if (stdout_handle != INVALID_HANDLE_VALUE)
      inherited_handle_list.push_back(stdout_handle);

    // Handles in the list must be unique.
    if (stderr_handle != stdout_handle && stderr_handle != INVALID_HANDLE_VALUE)
      inherited_handle_list.push_back(stderr_handle);

    const HandleList& policy_handle_list = policy_base->GetHandlesBeingShared();

    for (auto handle : policy_handle_list)
      inherited_handle_list.push_back(handle->Get());

    if (inherited_handle_list.size())
      ++attribute_count;

    if (!startup_info.InitializeProcThreadAttributeList(attribute_count))
      return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;

    if (app_container) {
      result = app_container->ShareForStartup(&startup_info);
      if (SBOX_ALL_OK != result)
        return result;
    }

    if (mitigations) {
      if (!startup_info.UpdateProcThreadAttribute(
               PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations,
               mitigations_size)) {
        return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
      }
    }

    if (inherited_handle_list.size()) {
      if (!startup_info.UpdateProcThreadAttribute(
              PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
              &inherited_handle_list[0],
              sizeof(HANDLE) * inherited_handle_list.size())) {
        return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
      }
      startup_info.startup_info()->dwFlags |= STARTF_USESTDHANDLES;
      startup_info.startup_info()->hStdInput = INVALID_HANDLE_VALUE;
      startup_info.startup_info()->hStdOutput = stdout_handle;
      startup_info.startup_info()->hStdError = stderr_handle;
      // Allowing inheritance of handles is only secure now that we
      // have limited which handles will be inherited.
      inherit_handles = true;
    }
  }

  // Construct the thread pool here in case it is expensive.
  // The thread pool is shared by all the targets
  if (NULL == thread_pool_)
    thread_pool_ = new Win2kThreadPool();

  // We need to temporarily mark all inherited handles as closeable. The handle
  // tracker may have marked the handles we're passing to the child as
  // non-closeable, but the child is getting new copies that it's allowed to
  // close. We're about to mark these handles as closeable for this process
  // (when we close them below in ClearSharedHandles()) but that will be too
  // late -- there will already another copy in the child that's non-closeable.
  // After launching we restore the non-closability of these handles. We don't
  // have any way here to affect *only* the child's copy, as the process
  // launching mechanism takes care of doing the duplication-with-the-same-value
  // into the child.
  std::vector<DWORD> inherited_handle_information(inherited_handle_list.size());
  for (size_t i = 0; i < inherited_handle_list.size(); ++i) {
    const HANDLE& inherited_handle = inherited_handle_list[i];
    ::GetHandleInformation(inherited_handle, &inherited_handle_information[i]);
    ::SetHandleInformation(inherited_handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
  }

  // Create the TargetProces object and spawn the target suspended. Note that
  // Brokerservices does not own the target object. It is owned by the Policy.
  base::win::ScopedProcessInformation process_info;
  TargetProcess* target =
      new TargetProcess(initial_token.Pass(), lockdown_token.Pass(),
                        lowbox_token.Pass(), job.Get(), thread_pool_);

  DWORD win_result = target->Create(exe_path, command_line, inherit_handles,
                                    startup_info, &process_info);

  // Restore the previous handle protection values.
  for (size_t i = 0; i < inherited_handle_list.size(); ++i) {
    ::SetHandleInformation(inherited_handle_list[i],
                           HANDLE_FLAG_PROTECT_FROM_CLOSE,
                           inherited_handle_information[i]);
  }

  policy_base->ClearSharedHandles();

  if (ERROR_SUCCESS != win_result) {
    SpawnCleanup(target, win_result);
    return SBOX_ERROR_CREATE_PROCESS;
  }

  // Now the policy is the owner of the target.
  if (!policy_base->AddTarget(target)) {
    return SpawnCleanup(target, 0);
  }

  // We are going to keep a pointer to the policy because we'll call it when
  // the job object generates notifications using the completion port.
  policy_base->AddRef();
  if (job.IsValid()) {
    scoped_ptr<JobTracker> tracker(new JobTracker(job.Pass(), policy_base));

    // There is no obvious recovery after failure here. Previous version with
    // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
    CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(),
                                  tracker.get()));

    // Save the tracker because in cleanup we might need to force closing
    // the Jobs.
    tracker_list_.push_back(tracker.release());
    child_process_ids_.insert(process_info.process_id());
  } else {
    // We have to signal the event once here because the completion port will
    // never get a message that this target is being terminated thus we should
    // not block WaitForAllTargets until we have at least one target with job.
    if (child_process_ids_.empty())
      ::SetEvent(no_targets_.Get());
    // We can not track the life time of such processes and it is responsibility
    // of the host application to make sure that spawned targets without jobs
    // are terminated when the main application don't need them anymore.
    // Sandbox policy engine needs to know that these processes are valid
    // targets for e.g. BrokerDuplicateHandle so track them as peer processes.
    AddTargetPeer(process_info.process_handle());
  }

  *target_info = process_info.Take();
  return SBOX_ALL_OK;
}


ResultCode BrokerServicesBase::WaitForAllTargets() {
  ::WaitForSingleObject(no_targets_.Get(), INFINITE);
  return SBOX_ALL_OK;
}

bool BrokerServicesBase::IsActiveTarget(DWORD process_id) {
  AutoLock lock(&lock_);
  return child_process_ids_.find(process_id) != child_process_ids_.end() ||
         peer_map_.find(process_id) != peer_map_.end();
}

VOID CALLBACK BrokerServicesBase::RemovePeer(PVOID parameter, BOOLEAN timeout) {
  PeerTracker* peer = reinterpret_cast<PeerTracker*>(parameter);
  // Don't check the return code because we this may fail (safely) at shutdown.
  ::PostQueuedCompletionStatus(
      peer->job_port, 0, THREAD_CTRL_REMOVE_PEER,
      reinterpret_cast<LPOVERLAPPED>(static_cast<uintptr_t>(peer->id)));
}

ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
  scoped_ptr<PeerTracker> peer(new PeerTracker(::GetProcessId(peer_process),
                                               job_port_.Get()));
  if (!peer->id)
    return SBOX_ERROR_GENERIC;

  HANDLE process_handle;
  if (!::DuplicateHandle(::GetCurrentProcess(), peer_process,
                         ::GetCurrentProcess(), &process_handle,
                         SYNCHRONIZE, FALSE, 0)) {
    return SBOX_ERROR_GENERIC;
  }
  peer->process.Set(process_handle);

  AutoLock lock(&lock_);
  if (!peer_map_.insert(std::make_pair(peer->id, peer.get())).second)
    return SBOX_ERROR_BAD_PARAMS;

  if (!::RegisterWaitForSingleObject(
          &peer->wait_object, peer->process.Get(), RemovePeer, peer.get(),
          INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) {
    peer_map_.erase(peer->id);
    return SBOX_ERROR_GENERIC;
  }

  // Release the pointer since it will be cleaned up by the callback.
  ignore_result(peer.release());
  return SBOX_ALL_OK;
}

ResultCode BrokerServicesBase::InstallAppContainer(const wchar_t* sid,
                                                   const wchar_t* name) {
  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
    return SBOX_ERROR_UNSUPPORTED;

  base::string16 old_name = LookupAppContainer(sid);
  if (old_name.empty())
    return CreateAppContainer(sid, name);

  if (old_name != name)
    return SBOX_ERROR_INVALID_APP_CONTAINER;

  return SBOX_ALL_OK;
}

ResultCode BrokerServicesBase::UninstallAppContainer(const wchar_t* sid) {
  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
    return SBOX_ERROR_UNSUPPORTED;

  base::string16 name = LookupAppContainer(sid);
  if (name.empty())
    return SBOX_ERROR_INVALID_APP_CONTAINER;

  return DeleteAppContainer(sid);
}

}  // namespace sandbox
