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

#include "base/win/com_init_check_hook.h"

#include <windows.h>

#include <objbase.h>
#include <stdint.h>
#include <string.h>

#include <ostream>
#include <string>

#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/win/com_init_util.h"
#include "base/win/patch_util.h"

namespace base {
namespace win {

#if defined(COM_INIT_CHECK_HOOK_ENABLED)

namespace {

// Hotpatchable Microsoft x86 32-bit functions take one of two forms:
// Newer format:
// RelAddr  Binary     Instruction                 Remarks
//      -5  cc         int 3
//      -4  cc         int 3
//      -3  cc         int 3
//      -2  cc         int 3
//      -1  cc         int 3
//       0  8bff       mov edi,edi                 Actual entry point and no-op.
//       2  ...                                    Actual body.
//
// Older format:
// RelAddr  Binary     Instruction                 Remarks
//      -5  90         nop
//      -4  90         nop
//      -3  90         nop
//      -2  90         nop
//      -1  90         nop
//       0  8bff       mov edi,edi                 Actual entry point and no-op.
//       2  ...                                    Actual body.
//
// The "int 3" or nop sled as well as entry point no-op are critical, as they
// are just enough to patch in a short backwards jump to -5 (2 bytes) then that
// can do a relative 32-bit jump about 2GB before or after the current address.
//
// To perform a hotpatch, we need to figure out where we want to go and where
// we are now as the final jump is relative. Let's say we want to jump to
// 0x12345678. Relative jumps are calculated from eip, which for our jump is the
// next instruction address. For the example above, that means we start at a 0
// base address.
//
// Our patch will then look as follows:
// RelAddr  Binary     Instruction                 Remarks
//      -5  e978563412 jmp 0x12345678-(-0x5+0x5)   Note little-endian format.
//       0  ebf9       jmp -0x5-(0x0+0x2)          Goes to RelAddr -0x5.
//       2  ...                                    Actual body.
// Note: The jmp instructions above are structured as
//       Address(Destination)-(Address(jmp Instruction)+sizeof(jmp Instruction))

// The struct below is provided for convenience and must be packed together byte
// by byte with no word alignment padding. This comes at a very small
// performance cost because now there are shifts handling the fields, but
// it improves readability.
#pragma pack(push, 1)
struct StructuredHotpatch {
  unsigned char jmp_32_relative = 0xe9;  // jmp relative 32-bit.
  int32_t relative_address = 0;          // 32-bit signed operand.
  unsigned char jmp_8_relative = 0xeb;   // jmp relative 8-bit.
  unsigned char back_address = 0xf9;     // Operand of -7.
};
#pragma pack(pop)

static_assert(sizeof(StructuredHotpatch) == 7,
              "Needs to be exactly 7 bytes for the hotpatch to work.");

// nop Function Padding with "mov edi,edi"
const unsigned char g_hotpatch_placeholder_nop[] = {0x90, 0x90, 0x90, 0x90,
                                                    0x90, 0x8b, 0xff};

// int 3 Function Padding with "mov edi,edi"
const unsigned char g_hotpatch_placeholder_int3[] = {0xcc, 0xcc, 0xcc, 0xcc,
                                                     0xcc, 0x8b, 0xff};

// http://crbug.com/1312659: Unusable apphelp placeholder missing one byte.
const unsigned char g_hotpatch_placeholder_apphelp[] = {0x00, 0xcc, 0xcc, 0xcc,
                                                        0xcc, 0x8b, 0xff};

class HookManager {
 public:
  static HookManager* GetInstance() {
    static auto* hook_manager = new HookManager();
    return hook_manager;
  }

  HookManager(const HookManager&) = delete;
  HookManager& operator=(const HookManager&) = delete;

  void RegisterHook() {
    AutoLock auto_lock(lock_);
    ++init_count_;
    if (disabled_)
      return;
    if (init_count_ == 1)
      WriteHook();
  }

  void UnregisterHook() {
    AutoLock auto_lock(lock_);
    DCHECK_NE(0U, init_count_);
    --init_count_;
    if (disabled_)
      return;
    if (init_count_ == 0)
      RevertHook();
  }

  void DisableCOMChecksForProcess() {
    AutoLock auto_lock(lock_);
    if (disabled_)
      return;
    disabled_ = true;
    if (init_count_ > 0)
      RevertHook();
  }

 private:
  enum class HotpatchPlaceholderFormat {
    // The hotpatch placeholder is currently unknown
    UNKNOWN,
    // The hotpatch placeholder used int 3's in the sled.
    INT3,
    // The hotpatch placeholder used nop's in the sled.
    NOP,
    // The hotpatch placeholder is an unusable apphelp shim.
    APPHELP_SHIM,
    // This function has already been patched by a different component.
    EXTERNALLY_PATCHED,
  };

  HookManager() = default;
  ~HookManager() = default;

  void WriteHook() {
    lock_.AssertAcquired();
    DCHECK(!ole32_library_);
    ole32_library_ = ::LoadLibrary(L"ole32.dll");

    if (!ole32_library_)
      return;

    // See banner comment above why this subtracts 5 bytes.
    co_create_instance_padded_address_ =
        reinterpret_cast<uint32_t>(
            GetProcAddress(ole32_library_, "CoCreateInstance")) -
        5;

    // See banner comment above why this adds 7 bytes.
    original_co_create_instance_body_function_ =
        reinterpret_cast<decltype(original_co_create_instance_body_function_)>(
            co_create_instance_padded_address_ + 7);

    uint32_t dchecked_co_create_instance_address =
        reinterpret_cast<uint32_t>(&HookManager::DCheckedCoCreateInstance);
    uint32_t jmp_offset_base_address = co_create_instance_padded_address_ + 5;
    structured_hotpatch_.relative_address = static_cast<int32_t>(
        dchecked_co_create_instance_address - jmp_offset_base_address);

    HotpatchPlaceholderFormat format = GetHotpatchPlaceholderFormat(
        reinterpret_cast<const void*>(co_create_instance_padded_address_));
    if (format == HotpatchPlaceholderFormat::UNKNOWN) {
      NOTREACHED() << "Unrecognized hotpatch function format: "
                   << FirstSevenBytesToString(
                          co_create_instance_padded_address_);
      return;
    } else if (format == HotpatchPlaceholderFormat::EXTERNALLY_PATCHED) {
      hotpatch_placeholder_format_ = format;
      NOTREACHED() << "CoCreateInstance appears to be previously patched. <"
                   << FirstSevenBytesToString(
                          co_create_instance_padded_address_)
                   << "> Attempted to write <"
                   << FirstSevenBytesToString(
                          reinterpret_cast<uint32_t>(&structured_hotpatch_))
                   << ">";
      return;
    } else if (format == HotpatchPlaceholderFormat::APPHELP_SHIM) {
      // The apphelp shim placeholder does not allocate enough bytes for a
      // trampolined jump. In this case, we skip patching.
      hotpatch_placeholder_format_ = format;
      return;
    }

    DCHECK_EQ(hotpatch_placeholder_format_, HotpatchPlaceholderFormat::UNKNOWN);
    DWORD patch_result = internal::ModifyCode(
        reinterpret_cast<void*>(co_create_instance_padded_address_),
        reinterpret_cast<void*>(&structured_hotpatch_),
        sizeof(structured_hotpatch_));
    if (patch_result == NO_ERROR)
      hotpatch_placeholder_format_ = format;
  }

  void RevertHook() {
    lock_.AssertAcquired();

    DWORD revert_result = NO_ERROR;
    switch (hotpatch_placeholder_format_) {
      case HotpatchPlaceholderFormat::INT3:
        if (WasHotpatchChanged())
          return;
        revert_result = internal::ModifyCode(
            reinterpret_cast<void*>(co_create_instance_padded_address_),
            reinterpret_cast<const void*>(&g_hotpatch_placeholder_int3),
            sizeof(g_hotpatch_placeholder_int3));
        break;
      case HotpatchPlaceholderFormat::NOP:
        if (WasHotpatchChanged())
          return;
        revert_result = internal::ModifyCode(
            reinterpret_cast<void*>(co_create_instance_padded_address_),
            reinterpret_cast<const void*>(&g_hotpatch_placeholder_nop),
            sizeof(g_hotpatch_placeholder_nop));
        break;
      case HotpatchPlaceholderFormat::EXTERNALLY_PATCHED:
      case HotpatchPlaceholderFormat::APPHELP_SHIM:
      case HotpatchPlaceholderFormat::UNKNOWN:
        break;
    }
    DCHECK_EQ(revert_result, static_cast<DWORD>(NO_ERROR))
        << "Failed to revert CoCreateInstance hot-patch";

    hotpatch_placeholder_format_ = HotpatchPlaceholderFormat::UNKNOWN;

    if (ole32_library_) {
      ::FreeLibrary(ole32_library_);
      ole32_library_ = nullptr;
    }

    co_create_instance_padded_address_ = 0;
    original_co_create_instance_body_function_ = nullptr;
  }

  HotpatchPlaceholderFormat GetHotpatchPlaceholderFormat(const void* address) {
    if (::memcmp(reinterpret_cast<void*>(co_create_instance_padded_address_),
                 reinterpret_cast<const void*>(&g_hotpatch_placeholder_int3),
                 sizeof(g_hotpatch_placeholder_int3)) == 0) {
      return HotpatchPlaceholderFormat::INT3;
    }

    if (::memcmp(reinterpret_cast<void*>(co_create_instance_padded_address_),
                 reinterpret_cast<const void*>(&g_hotpatch_placeholder_nop),
                 sizeof(g_hotpatch_placeholder_nop)) == 0) {
      return HotpatchPlaceholderFormat::NOP;
    }

    if (::memcmp(reinterpret_cast<void*>(co_create_instance_padded_address_),
                 reinterpret_cast<const void*>(&g_hotpatch_placeholder_apphelp),
                 sizeof(g_hotpatch_placeholder_apphelp)) == 0) {
      return HotpatchPlaceholderFormat::APPHELP_SHIM;
    }

    const unsigned char* instruction_bytes =
        reinterpret_cast<const unsigned char*>(
            co_create_instance_padded_address_);
    const unsigned char entry_point_byte = instruction_bytes[5];
    // Check for all of the common jmp opcodes.
    if (entry_point_byte == 0xeb || entry_point_byte == 0xe9 ||
        entry_point_byte == 0xff || entry_point_byte == 0xea) {
      return HotpatchPlaceholderFormat::EXTERNALLY_PATCHED;
    }

    return HotpatchPlaceholderFormat::UNKNOWN;
  }

  bool WasHotpatchChanged() {
    if (::memcmp(reinterpret_cast<void*>(co_create_instance_padded_address_),
                 reinterpret_cast<const void*>(&structured_hotpatch_),
                 sizeof(structured_hotpatch_)) == 0) {
      return false;
    }

    NOTREACHED() << "CoCreateInstance patch overwritten. Expected: <"
                 << FirstSevenBytesToString(co_create_instance_padded_address_)
                 << ">, Actual: <"
                 << FirstSevenBytesToString(
                        reinterpret_cast<uint32_t>(&structured_hotpatch_))
                 << ">";
    return true;
  }

  // Indirect call to original_co_create_instance_body_function_ triggers CFI
  // so this function must have CFI disabled.
  static DISABLE_CFI_ICALL HRESULT __stdcall DCheckedCoCreateInstance(
      const CLSID& rclsid,
      IUnknown* pUnkOuter,
      DWORD dwClsContext,
      REFIID riid,
      void** ppv) {
    // Chromium COM callers need to make sure that their thread is configured to
    // process COM objects to avoid creating an implicit MTA or silently failing
    // STA object creation call due to the SUCCEEDED() pattern for COM calls.
    //
    // If you hit this assert as part of migrating to the Task Scheduler,
    // evaluate your threading guarantees and dispatch your work with
    // base::ThreadPool::CreateCOMSTATaskRunner().
    //
    // If you need MTA support, ping //base/task/thread_pool/OWNERS.
    AssertComInitialized(
        "CoCreateInstance calls in Chromium require explicit COM "
        "initialization via base::ThreadPool::CreateCOMSTATaskRunner() or "
        "ScopedCOMInitializer. See the comment in DCheckedCoCreateInstance for "
        "more details.");
    return original_co_create_instance_body_function_(rclsid, pUnkOuter,
                                                      dwClsContext, riid, ppv);
  }

  // Returns the first 7 bytes in hex as a string at |address|.
  static std::string FirstSevenBytesToString(uint32_t address) {
    const unsigned char* bytes =
        reinterpret_cast<const unsigned char*>(address);
    return base::StringPrintf("%02x %02x %02x %02x %02x %02x %02x", bytes[0],
                              bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
                              bytes[6]);
  }

  // Synchronizes everything in this class.
  base::Lock lock_;
  size_t init_count_ = 0;
  bool disabled_ = false;
  HMODULE ole32_library_ = nullptr;
  uint32_t co_create_instance_padded_address_ = 0;
  HotpatchPlaceholderFormat hotpatch_placeholder_format_ =
      HotpatchPlaceholderFormat::UNKNOWN;
  StructuredHotpatch structured_hotpatch_;
  static decltype(
      ::CoCreateInstance)* original_co_create_instance_body_function_;
};

decltype(::CoCreateInstance)*
    HookManager::original_co_create_instance_body_function_ = nullptr;

}  // namespace

#endif  // defined(COM_INIT_CHECK_HOOK_ENABLED)

ComInitCheckHook::ComInitCheckHook() {
#if defined(COM_INIT_CHECK_HOOK_ENABLED)
  HookManager::GetInstance()->RegisterHook();
#endif  // defined(COM_INIT_CHECK_HOOK_ENABLED)
}

ComInitCheckHook::~ComInitCheckHook() {
#if defined(COM_INIT_CHECK_HOOK_ENABLED)
  HookManager::GetInstance()->UnregisterHook();
#endif  // defined(COM_INIT_CHECK_HOOK_ENABLED)
}

void ComInitCheckHook::DisableCOMChecksForProcess() {
#if defined(COM_INIT_CHECK_HOOK_ENABLED)
  HookManager::GetInstance()->DisableCOMChecksForProcess();
#endif
}

}  // namespace win
}  // namespace base
