chromium/sandbox/win/src/signed_policy.cc

// Copyright 2019 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/signed_policy.h"

#include <ntstatus.h>
#include <stdint.h>

#include <string>

#include "sandbox/win/src/ipc_tags.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_policy.h"
#include "sandbox/win/src/win_utils.h"

namespace sandbox {

bool SignedPolicy::GenerateRules(const wchar_t* name,
                                 LowLevelPolicy* policy) {
  base::FilePath file_path(name);
  auto nt_path_name = GetNtPathFromWin32Path(file_path.DirName().value());
  if (!nt_path_name)
    return false;

  base::FilePath nt_path(nt_path_name.value());
  std::wstring nt_filename = nt_path.Append(file_path.BaseName()).value();
  // Create a rule to ASK_BROKER if name matches.
  PolicyRule signed_policy(ASK_BROKER);
  if (!signed_policy.AddStringMatch(IF, NameBased::NAME, nt_filename.c_str())) {
    return false;
  }
  if (!policy->AddRule(IpcTag::NTCREATESECTION, &signed_policy)) {
    return false;
  }

  return true;
}

NTSTATUS SignedPolicy::CreateSectionAction(
    EvalResult eval_result,
    const ClientInfo& client_info,
    const base::win::ScopedHandle& local_file_handle,
    HANDLE* target_section_handle) {
  // The only action supported is ASK_BROKER which means create the requested
  // section as specified.
  if (ASK_BROKER != eval_result)
    return false;

  HANDLE local_section_handle = nullptr;
  NTSTATUS status = GetNtExports()->CreateSection(
      &local_section_handle,
      SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ |
          SECTION_MAP_EXECUTE,
      nullptr, 0, PAGE_EXECUTE, SEC_IMAGE, local_file_handle.get());
  if (!local_section_handle)
    return status;

  // Duplicate section handle back to the target.
  if (!::DuplicateHandle(::GetCurrentProcess(), local_section_handle,
                         client_info.process, target_section_handle, 0, false,
                         DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
    return STATUS_ACCESS_DENIED;
  }
  return status;
}

}  // namespace sandbox