// Copyright (c) 2011 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 "base/memory/shared_memory.h"

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

#include "base/allocator/partition_allocator/page_allocator.h"
#include "base/logging.h"
#include "base/memory/shared_memory_tracker.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/unguessable_token.h"

namespace base {
namespace {

// Errors that can occur during Shared Memory construction.
// These match tools/metrics/histograms/histograms.xml.
// This enum is append-only.
enum CreateError {
  SUCCESS = 0,
  SIZE_ZERO = 1,
  SIZE_TOO_LARGE = 2,
  INITIALIZE_ACL_FAILURE = 3,
  INITIALIZE_SECURITY_DESC_FAILURE = 4,
  SET_SECURITY_DESC_FAILURE = 5,
  CREATE_FILE_MAPPING_FAILURE = 6,
  REDUCE_PERMISSIONS_FAILURE = 7,
  ALREADY_EXISTS = 8,
  CREATE_ERROR_LAST = ALREADY_EXISTS
};

// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror|
// if there is no associated Windows error.
void LogError(CreateError error, DWORD winerror) {
  UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error,
                            CREATE_ERROR_LAST + 1);
  static_assert(ERROR_SUCCESS == 0, "Windows error code changed!");
  if (winerror != ERROR_SUCCESS)
    UmaHistogramSparse("SharedMemory.CreateWinError", winerror);
}

typedef enum _SECTION_INFORMATION_CLASS {
  SectionBasicInformation,
} SECTION_INFORMATION_CLASS;

typedef struct _SECTION_BASIC_INFORMATION {
  PVOID BaseAddress;
  ULONG Attributes;
  LARGE_INTEGER Size;
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;

typedef ULONG(__stdcall* NtQuerySectionType)(
    HANDLE SectionHandle,
    SECTION_INFORMATION_CLASS SectionInformationClass,
    PVOID SectionInformation,
    ULONG SectionInformationLength,
    PULONG ResultLength);

// Returns the length of the memory section starting at the supplied address.
size_t GetMemorySectionSize(void* address) {
  MEMORY_BASIC_INFORMATION memory_info;
  if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
    return 0;
  return memory_info.RegionSize - (static_cast<char*>(address) -
         static_cast<char*>(memory_info.AllocationBase));
}

// Checks if the section object is safe to map. At the moment this just means
// it's not an image section.
bool IsSectionSafeToMap(HANDLE handle) {
  static NtQuerySectionType nt_query_section_func;
  if (!nt_query_section_func) {
    nt_query_section_func = reinterpret_cast<NtQuerySectionType>(
        ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
    DCHECK(nt_query_section_func);
  }

  // The handle must have SECTION_QUERY access for this to succeed.
  SECTION_BASIC_INFORMATION basic_information = {};
  ULONG status =
      nt_query_section_func(handle, SectionBasicInformation, &basic_information,
                            sizeof(basic_information), nullptr);
  if (status)
    return false;
  return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
}

// Returns a HANDLE on success and |nullptr| on failure.
// This function is similar to CreateFileMapping, but removes the permissions
// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE.
//
// A newly created file mapping has two sets of permissions. It has access
// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and
// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle()
// with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions.
//
// The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being
// duplicated into unprivileged processes. But the only way to copy file
// permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that
// there is no way for a privileged process to duplicate a file mapping into an
// unprivileged process while maintaining the previous file permissions.
//
// By removing all access control permissions of a file mapping immediately
// after creation, ::DuplicateHandle() effectively only copies the file
// permissions.
HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa,
                                               size_t rounded_size,
                                               LPCWSTR name) {
  HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0,
                               static_cast<DWORD>(rounded_size), name);
  if (!h) {
    LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError());
    return nullptr;
  }

  HANDLE h2;
  BOOL success = ::DuplicateHandle(
      GetCurrentProcess(), h, GetCurrentProcess(), &h2,
      FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0);
  BOOL rv = ::CloseHandle(h);
  DCHECK(rv);

  if (!success) {
    LogError(REDUCE_PERMISSIONS_FAILURE, GetLastError());
    return nullptr;
  }

  return h2;
}

}  // namespace.

SharedMemory::SharedMemory() {}

SharedMemory::SharedMemory(const string16& name) : name_(name) {}

SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
    : external_section_(true), shm_(handle), read_only_(read_only) {}

SharedMemory::~SharedMemory() {
  Unmap();
  Close();
}

// static
bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
  return handle.IsValid();
}

// static
void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
  handle.Close();
}

// static
size_t SharedMemory::GetHandleLimit() {
  // Rounded down from value reported here:
  // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx
  return static_cast<size_t>(1 << 23);
}

// static
SharedMemoryHandle SharedMemory::DuplicateHandle(
    const SharedMemoryHandle& handle) {
  return handle.Duplicate();
}

bool SharedMemory::CreateAndMapAnonymous(size_t size) {
  return CreateAnonymous(size) && Map(size);
}

bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
  // TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k
  // per mapping on average.
  static const size_t kSectionMask = 65536 - 1;
  DCHECK(!options.executable);
  DCHECK(!shm_.IsValid());
  if (options.size == 0) {
    LogError(SIZE_ZERO, 0);
    return false;
  }

  // Check maximum accounting for overflow.
  if (options.size >
      static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) {
    LogError(SIZE_TOO_LARGE, 0);
    return false;
  }

  size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask;
  name_ = options.name_deprecated ?
      ASCIIToUTF16(*options.name_deprecated) : L"";
  SECURITY_ATTRIBUTES sa = {sizeof(sa), nullptr, FALSE};
  SECURITY_DESCRIPTOR sd;
  ACL dacl;

  if (name_.empty()) {
    // Add an empty DACL to enforce anonymous read-only sections.
    sa.lpSecurityDescriptor = &sd;
    if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) {
      LogError(INITIALIZE_ACL_FAILURE, GetLastError());
      return false;
    }
    if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
      LogError(INITIALIZE_SECURITY_DESC_FAILURE, GetLastError());
      return false;
    }
    if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) {
      LogError(SET_SECURITY_DESC_FAILURE, GetLastError());
      return false;
    }

    // Windows ignores DACLs on certain unnamed objects (like shared sections).
    // So, we generate a random name when we need to enforce read-only.
    uint64_t rand_values[4];
    RandBytes(&rand_values, sizeof(rand_values));
    name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx",
                         rand_values[0], rand_values[1],
                         rand_values[2], rand_values[3]);
  }
  DCHECK(!name_.empty());
  shm_ = SharedMemoryHandle(
      CreateFileMappingWithReducedPermissions(&sa, rounded_size, name_.c_str()),
      rounded_size, UnguessableToken::Create());
  if (!shm_.IsValid()) {
    // The error is logged within CreateFileMappingWithReducedPermissions().
    return false;
  }

  requested_size_ = options.size;

  // Check if the shared memory pre-exists.
  if (GetLastError() == ERROR_ALREADY_EXISTS) {
    // If the file already existed, set requested_size_ to 0 to show that
    // we don't know the size.
    requested_size_ = 0;
    external_section_ = true;
    if (!options.open_existing_deprecated) {
      Close();
      // From "if" above: GetLastError() == ERROR_ALREADY_EXISTS.
      LogError(ALREADY_EXISTS, ERROR_ALREADY_EXISTS);
      return false;
    }
  }

  LogError(SUCCESS, ERROR_SUCCESS);
  return true;
}

bool SharedMemory::Delete(const std::string& name) {
  // intentionally empty -- there is nothing for us to do on Windows.
  return true;
}

bool SharedMemory::Open(const std::string& name, bool read_only) {
  DCHECK(!shm_.IsValid());
  DWORD access = FILE_MAP_READ | SECTION_QUERY;
  if (!read_only)
    access |= FILE_MAP_WRITE;
  name_ = ASCIIToUTF16(name);
  read_only_ = read_only;

  // This form of sharing shared memory is deprecated. https://crbug.com/345734.
  // However, we can't get rid of it without a significant refactor because its
  // used to communicate between two versions of the same service process, very
  // early in the life cycle.
  // Technically, we should also pass the GUID from the original shared memory
  // region. We don't do that - this means that we will overcount this memory,
  // which thankfully isn't relevant since Chrome only communicates with a
  // single version of the service process.
  // We pass the size |0|, which is a dummy size and wrong, but otherwise
  // harmless.
  shm_ = SharedMemoryHandle(
      OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str()),
      0u, UnguessableToken::Create());
  if (!shm_.IsValid())
    return false;
  // If a name specified assume it's an external section.
  if (!name_.empty())
    external_section_ = true;
  // Note: size_ is not set in this case.
  return true;
}

bool SharedMemory::MapAt(off_t offset, size_t bytes) {
  if (!shm_.IsValid()) {
    DLOG(ERROR) << "Invalid SharedMemoryHandle.";
    return false;
  }

  if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
    DLOG(ERROR) << "Bytes required exceeds the 2G limitation.";
    return false;
  }

  if (memory_) {
    DLOG(ERROR) << "The SharedMemory has been mapped already.";
    return false;
  }

  if (external_section_ && !IsSectionSafeToMap(shm_.GetHandle())) {
    DLOG(ERROR) << "SharedMemoryHandle is not safe to be mapped.";
    return false;
  }

  // Try to map the shared memory. On the first failure, release any reserved
  // address space for a single retry.
  for (int i = 0; i < 2; ++i) {
    memory_ = MapViewOfFile(
        shm_.GetHandle(),
        read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE,
        static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes);
    if (memory_)
      break;
    ReleaseReservation();
  }
  if (!memory_) {
    DPLOG(ERROR) << "Failed executing MapViewOfFile";
    return false;
  }

  DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
                    (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
  mapped_size_ = GetMemorySectionSize(memory_);
  mapped_id_ = shm_.GetGUID();
  SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this);
  return true;
}

bool SharedMemory::Unmap() {
  if (!memory_)
    return false;

  SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this);
  UnmapViewOfFile(memory_);
  memory_ = nullptr;
  mapped_id_ = UnguessableToken();
  return true;
}

SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const {
  HANDLE result;
  ProcessHandle process = GetCurrentProcess();
  if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result,
                         FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) {
    return SharedMemoryHandle();
  }
  SharedMemoryHandle handle =
      SharedMemoryHandle(result, shm_.GetSize(), shm_.GetGUID());
  handle.SetOwnershipPassesToIPC(true);
  return handle;
}

void SharedMemory::Close() {
  if (shm_.IsValid()) {
    shm_.Close();
    shm_ = SharedMemoryHandle();
  }
}

SharedMemoryHandle SharedMemory::handle() const {
  return shm_;
}

SharedMemoryHandle SharedMemory::TakeHandle() {
  SharedMemoryHandle handle(shm_);
  handle.SetOwnershipPassesToIPC(true);
  Unmap();
  shm_ = SharedMemoryHandle();
  return handle;
}

}  // namespace base
