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_freestanding_ModuleLoadFrame_h 8 #define mozilla_freestanding_ModuleLoadFrame_h 9 10 #include "mozilla/LoaderAPIInterfaces.h" 11 #include "mozilla/NativeNt.h" 12 #include "mozilla/ThreadLocal.h" 13 14 #include "SafeThreadLocal.h" 15 16 namespace mozilla { 17 namespace freestanding { 18 19 /** 20 * This class holds information about a DLL load at a particular frame in the 21 * current thread's stack. Each instance adds itself to a thread-local linked 22 * list of ModuleLoadFrames, enabling us to query information about the 23 * previous module load on the stack. 24 */ 25 class MOZ_RAII ModuleLoadFrame final { 26 public: 27 /** 28 * This constructor is for use by the LdrLoadDll hook. 29 */ 30 explicit ModuleLoadFrame(PCUNICODE_STRING aRequestedDllName); 31 ~ModuleLoadFrame(); 32 33 static void NotifyLSPSubstitutionRequired(PCUNICODE_STRING aLeafName); 34 35 /** 36 * This static method is called by the NtMapViewOfSection hook. 37 */ 38 static void NotifySectionMap(nt::AllocatedUnicodeString&& aSectionName, 39 const void* aMapBaseAddr, NTSTATUS aMapNtStatus, 40 ModuleLoadInfo::Status aLoadStatus, 41 bool aIsDependent); 42 static bool ExistsTopFrame(); 43 44 /** 45 * Called by the LdrLoadDll hook to indicate the status of the load and for 46 * us to provide a substitute output handle if necessary. 47 */ 48 NTSTATUS SetLoadStatus(NTSTATUS aNtStatus, PHANDLE aOutHandle); 49 50 ModuleLoadFrame(const ModuleLoadFrame&) = delete; 51 ModuleLoadFrame(ModuleLoadFrame&&) = delete; 52 ModuleLoadFrame& operator=(const ModuleLoadFrame&) = delete; 53 ModuleLoadFrame& operator=(ModuleLoadFrame&&) = delete; 54 55 private: 56 /** 57 * Called by OnBareSectionMap to construct a frame for a bare load. 58 */ 59 ModuleLoadFrame(nt::AllocatedUnicodeString&& aSectionName, 60 const void* aMapBaseAddr, NTSTATUS aNtStatus, 61 ModuleLoadInfo::Status aLoadStatus, bool aIsDependent); 62 63 void SetLSPSubstitutionRequired(PCUNICODE_STRING aLeafName); 64 void OnSectionMap(nt::AllocatedUnicodeString&& aSectionName, 65 const void* aMapBaseAddr, NTSTATUS aMapNtStatus, 66 ModuleLoadInfo::Status aLoadStatus, bool aIsDependent); 67 68 /** 69 * A "bare" section mapping is one that was mapped without the code passing 70 * through a call to ntdll!LdrLoadDll. This method is invoked when we detect 71 * that condition. 72 */ 73 static void OnBareSectionMap(nt::AllocatedUnicodeString&& aSectionName, 74 const void* aMapBaseAddr, NTSTATUS aMapNtStatus, 75 ModuleLoadInfo::Status aLoadStatus, 76 bool aIsDependent); 77 78 private: 79 // Link to the previous frame 80 ModuleLoadFrame* mPrev; 81 // Pointer to context managed by the nt::LoaderObserver implementation 82 void* mContext; 83 // Set to |true| when we need to block a WinSock LSP 84 bool mLSPSubstitutionRequired; 85 // NTSTATUS code from the |LdrLoadDll| call 86 NTSTATUS mLoadNtStatus; 87 // Telemetry information that will be forwarded to the nt::LoaderObserver 88 ModuleLoadInfo mLoadInfo; 89 90 // Head of the linked list 91 static SafeThreadLocal<ModuleLoadFrame*> sTopFrame; 92 }; 93 94 } // namespace freestanding 95 } // namespace mozilla 96 97 #endif // mozilla_freestanding_ModuleLoadFrame_h 98