tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ProcThreadAttributes.h (4877B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_ProcThreadAttributes_h
      8 #define mozilla_ProcThreadAttributes_h
      9 
     10 #include <windows.h>
     11 
     12 #include <utility>
     13 
     14 #include "mozilla/UniquePtr.h"
     15 #include "mozilla/Vector.h"
     16 
     17 namespace mozilla {
     18 
     19 class MOZ_RAII ProcThreadAttributes final {
     20  struct ProcThreadAttributeListDeleter {
     21    void operator()(LPPROC_THREAD_ATTRIBUTE_LIST aList) {
     22      ::DeleteProcThreadAttributeList(aList);
     23      delete[] reinterpret_cast<char*>(aList);
     24    }
     25  };
     26 
     27  using ProcThreadAttributeListPtr =
     28      UniquePtr<_PROC_THREAD_ATTRIBUTE_LIST, ProcThreadAttributeListDeleter>;
     29 
     30 public:
     31  ProcThreadAttributes() : mMitigationPolicies(0) {}
     32 
     33  ~ProcThreadAttributes() = default;
     34 
     35  ProcThreadAttributes(const ProcThreadAttributes&) = delete;
     36  ProcThreadAttributes(ProcThreadAttributes&&) = delete;
     37  ProcThreadAttributes& operator=(const ProcThreadAttributes&) = delete;
     38  ProcThreadAttributes& operator=(ProcThreadAttributes&&) = delete;
     39 
     40  void AddMitigationPolicy(DWORD64 aPolicy) { mMitigationPolicies |= aPolicy; }
     41 
     42  bool AddInheritableHandle(HANDLE aHandle) {
     43    DWORD type = ::GetFileType(aHandle);
     44    if (type != FILE_TYPE_DISK && type != FILE_TYPE_PIPE) {
     45      return false;
     46    }
     47 
     48    if (!::SetHandleInformation(aHandle, HANDLE_FLAG_INHERIT,
     49                                HANDLE_FLAG_INHERIT)) {
     50      return false;
     51    }
     52 
     53    return mInheritableHandles.append(aHandle);
     54  }
     55 
     56  template <size_t N>
     57  bool AddInheritableHandles(HANDLE (&aHandles)[N]) {
     58    bool ok = true;
     59    for (auto handle : aHandles) {
     60      ok &= AddInheritableHandle(handle);
     61    }
     62 
     63    return ok;
     64  }
     65 
     66  bool HasMitigationPolicies() const { return !!mMitigationPolicies; }
     67 
     68  bool HasInheritableHandles() const { return !mInheritableHandles.empty(); }
     69 
     70  /**
     71   * @return false if the STARTUPINFOEXW::lpAttributeList was set to null
     72   *               as expected based on the state of |this|;
     73   *         true  if the STARTUPINFOEXW::lpAttributeList was set to
     74   *               non-null;
     75   */
     76  LauncherResult<bool> AssignTo(STARTUPINFOEXW& aSiex) {
     77    ZeroMemory(&aSiex, sizeof(STARTUPINFOEXW));
     78 
     79    // We'll set the size to sizeof(STARTUPINFOW) until we determine whether the
     80    // extended fields will be used.
     81    aSiex.StartupInfo.cb = sizeof(STARTUPINFOW);
     82 
     83    DWORD numAttributes = 0;
     84    if (HasMitigationPolicies()) {
     85      ++numAttributes;
     86    }
     87 
     88    if (HasInheritableHandles()) {
     89      ++numAttributes;
     90    }
     91 
     92    if (!numAttributes) {
     93      return false;
     94    }
     95 
     96    SIZE_T listSize = 0;
     97    if (!::InitializeProcThreadAttributeList(nullptr, numAttributes, 0,
     98                                             &listSize)) {
     99      DWORD err = ::GetLastError();
    100      if (err != ERROR_INSUFFICIENT_BUFFER) {
    101        return LAUNCHER_ERROR_FROM_WIN32(err);
    102      }
    103    }
    104 
    105    auto buf = MakeUnique<char[]>(listSize);
    106 
    107    LPPROC_THREAD_ATTRIBUTE_LIST tmpList =
    108        reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(buf.get());
    109 
    110    if (!::InitializeProcThreadAttributeList(tmpList, numAttributes, 0,
    111                                             &listSize)) {
    112      return LAUNCHER_ERROR_FROM_LAST();
    113    }
    114 
    115    // Transfer buf to a ProcThreadAttributeListPtr - now that the list is
    116    // initialized, we are no longer dealing with a plain old char array. We
    117    // must now deinitialize the attribute list before deallocating the
    118    // underlying buffer.
    119    ProcThreadAttributeListPtr attrList(
    120        reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(buf.release()));
    121 
    122    if (mMitigationPolicies) {
    123      if (!::UpdateProcThreadAttribute(
    124              attrList.get(), 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
    125              &mMitigationPolicies, sizeof(mMitigationPolicies), nullptr,
    126              nullptr)) {
    127        return LAUNCHER_ERROR_FROM_LAST();
    128      }
    129    }
    130 
    131    if (!mInheritableHandles.empty()) {
    132      if (!::UpdateProcThreadAttribute(
    133              attrList.get(), 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
    134              mInheritableHandles.begin(),
    135              mInheritableHandles.length() * sizeof(HANDLE), nullptr,
    136              nullptr)) {
    137        return LAUNCHER_ERROR_FROM_LAST();
    138      }
    139    }
    140 
    141    mAttrList = std::move(attrList);
    142    aSiex.lpAttributeList = mAttrList.get();
    143    aSiex.StartupInfo.cb = sizeof(STARTUPINFOEXW);
    144    return true;
    145  }
    146 
    147 private:
    148  static const uint32_t kNumInline = 3;  // Inline storage for the std handles
    149 
    150  DWORD64 mMitigationPolicies;
    151  Vector<HANDLE, kNumInline> mInheritableHandles;
    152  ProcThreadAttributeListPtr mAttrList;
    153 };
    154 
    155 }  // namespace mozilla
    156 
    157 #endif  // mozilla_ProcThreadAttributes_h