chromium/sandbox/win/src/process_thread_dispatcher.cc

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include <stddef.h>
#include <stdint.h>

#include "base/notreached.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/interceptors.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/process_thread_interception.h"
#include "sandbox/win/src/process_thread_policy.h"
#include "sandbox/win/src/sandbox.h"

namespace sandbox {

ThreadProcessDispatcher::ThreadProcessDispatcher() {
  static const IPCCall open_thread = {
      {IpcTag::NTOPENTHREAD, {UINT32_TYPE, UINT32_TYPE}},
      reinterpret_cast<CallbackGeneric>(
          &ThreadProcessDispatcher::NtOpenThread)};

  static const IPCCall process_tokenex = {
      {IpcTag::NTOPENPROCESSTOKENEX, {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE}},
      reinterpret_cast<CallbackGeneric>(
          &ThreadProcessDispatcher::NtOpenProcessTokenEx)};

  // NOTE(liamjm): 2nd param is size_t: Using VOIDPTR_TYPE as they are
  // the same size on windows.
  static_assert(sizeof(size_t) == sizeof(void*),
                "VOIDPTR_TYPE not same size as size_t");
  static const IPCCall create_thread_params = {
      {IpcTag::CREATETHREAD,
       {VOIDPTR_TYPE, VOIDPTR_TYPE, VOIDPTR_TYPE, UINT32_TYPE}},
      reinterpret_cast<CallbackGeneric>(
          &ThreadProcessDispatcher::CreateThread)};

  ipc_calls_.push_back(open_thread);
  ipc_calls_.push_back(process_tokenex);
  ipc_calls_.push_back(create_thread_params);
}

bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager,
                                           IpcTag service) {
  switch (service) {
    case IpcTag::NTOPENTHREAD:
    case IpcTag::NTOPENPROCESSTOKENEX:
    case IpcTag::CREATETHREAD:
      // There is no explicit policy for these services.
      // Intercepts are set up in SetupBasicInterceptions(), not here.
      NOTREACHED_IN_MIGRATION();
      return false;

    default:
      return false;
  }
}

bool ThreadProcessDispatcher::NtOpenThread(IPCInfo* ipc,
                                           uint32_t desired_access,
                                           uint32_t thread_id) {
  HANDLE handle;
  NTSTATUS ret = ProcessPolicy::OpenThreadAction(
      *ipc->client_info, desired_access, thread_id, &handle);
  ipc->return_info.nt_status = ret;
  ipc->return_info.handle = handle;
  return true;
}

bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc,
                                                   HANDLE process,
                                                   uint32_t desired_access,
                                                   uint32_t attributes) {
  HANDLE handle;
  NTSTATUS ret = ProcessPolicy::OpenProcessTokenExAction(
      *ipc->client_info, process, desired_access, attributes, &handle);
  ipc->return_info.nt_status = ret;
  ipc->return_info.handle = handle;
  return true;
}

bool ThreadProcessDispatcher::CreateThread(IPCInfo* ipc,
                                           SIZE_T stack_size,
                                           LPTHREAD_START_ROUTINE start_address,
                                           LPVOID parameter,
                                           DWORD creation_flags) {
  if (!start_address) {
    return false;
  }

  HANDLE handle;
  DWORD ret = ProcessPolicy::CreateThreadAction(*ipc->client_info, stack_size,
                                                start_address, parameter,
                                                creation_flags, &handle);

  ipc->return_info.win32_result = ret;
  ipc->return_info.handle = handle;
  return true;
}

}  // namespace sandbox