// Copyright 2011 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_policy.h"
#include <ntstatus.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/memory/free_deleter.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/policy_engine_opcodes.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/win_utils.h"
namespace sandbox {
NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
uint32_t desired_access,
uint32_t thread_id,
HANDLE* handle) {
*handle = nullptr;
OBJECT_ATTRIBUTES attributes = {0};
attributes.Length = sizeof(attributes);
CLIENT_ID client_id = {0};
client_id.UniqueProcess =
reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(client_info.process_id));
client_id.UniqueThread =
reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(thread_id));
HANDLE local_handle = nullptr;
NTSTATUS status = GetNtExports()->OpenThread(&local_handle, desired_access,
&attributes, &client_id);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
return STATUS_ACCESS_DENIED;
}
}
return status;
}
NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info,
HANDLE process,
uint32_t desired_access,
uint32_t attributes,
HANDLE* handle) {
*handle = nullptr;
if (CURRENT_PROCESS != process)
return STATUS_ACCESS_DENIED;
HANDLE local_handle = nullptr;
NTSTATUS status = GetNtExports()->OpenProcessTokenEx(
client_info.process, desired_access, attributes, &local_handle);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
return STATUS_ACCESS_DENIED;
}
}
return status;
}
DWORD ProcessPolicy::CreateThreadAction(
const ClientInfo& client_info,
const SIZE_T stack_size,
const LPTHREAD_START_ROUTINE start_address,
const LPVOID parameter,
const DWORD creation_flags,
HANDLE* handle) {
*handle = nullptr;
base::win::ScopedHandle local_handle(
::CreateRemoteThread(client_info.process, nullptr, stack_size,
start_address, parameter, creation_flags, nullptr));
if (!local_handle.is_valid()) {
return ::GetLastError();
}
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle.get(),
client_info.process, handle, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
return ERROR_ACCESS_DENIED;
}
return ERROR_SUCCESS;
}
} // namespace sandbox