diff options
Diffstat (limited to 'toolkit/xre/dllservices/UntrustedModulesProcessor.h')
-rw-r--r-- | toolkit/xre/dllservices/UntrustedModulesProcessor.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/toolkit/xre/dllservices/UntrustedModulesProcessor.h b/toolkit/xre/dllservices/UntrustedModulesProcessor.h new file mode 100644 index 0000000000..b91d88961a --- /dev/null +++ b/toolkit/xre/dllservices/UntrustedModulesProcessor.h @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_UntrustedModulesProcessor_h +#define mozilla_UntrustedModulesProcessor_h + +#include "mozilla/Atomics.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/glue/WindowsDllServices.h" +#include "mozilla/LazyIdleThread.h" +#include "mozilla/Maybe.h" +#include "mozilla/MozPromise.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UntrustedModulesData.h" +#include "mozilla/Vector.h" +#include "mozilla/WinHeaderOnlyUtils.h" +#include "nsCOMPtr.h" +#include "nsIObserver.h" +#include "nsIRunnable.h" +#include "nsISupportsImpl.h" +#include "nsString.h" + +namespace mozilla { + +class ModuleEvaluator; + +using UntrustedModulesPromise = + MozPromise<Maybe<UntrustedModulesData>, nsresult, true>; + +using ModulesTrustPromise = MozPromise<ModulesMapResult, nsresult, true>; + +using GetModulesTrustIpcPromise = + MozPromise<Maybe<ModulesMapResult>, ipc::ResponseRejectReason, true>; + +struct UnprocessedModuleLoadInfoContainer final + : public LinkedListElement<UnprocessedModuleLoadInfoContainer> { + glue::EnhancedModuleLoadInfo mInfo; + + template <typename T> + explicit UnprocessedModuleLoadInfoContainer(T&& aInfo) + : mInfo(std::move(aInfo)) {} + + UnprocessedModuleLoadInfoContainer( + const UnprocessedModuleLoadInfoContainer&) = delete; + UnprocessedModuleLoadInfoContainer& operator=( + const UnprocessedModuleLoadInfoContainer&) = delete; +}; +using UnprocessedModuleLoads = + AutoCleanLinkedList<UnprocessedModuleLoadInfoContainer>; + +class UntrustedModulesProcessor final : public nsIObserver, + public nsIThreadPoolListener { + public: + static RefPtr<UntrustedModulesProcessor> Create( + bool aIsReadyForBackgroundProcessing); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIOBSERVER + NS_DECL_NSITHREADPOOLLISTENER + + // Called to check if the parent process is ready when a child process + // is spanwed + bool IsReadyForBackgroundProcessing() const; + + // Called by DLL Services to explicitly begin shutting down + void Disable(); + + // Called by DLL Services to submit module load data to the processor + void Enqueue(glue::EnhancedModuleLoadInfo&& aModLoadInfo); + void Enqueue(ModuleLoadInfoVec&& aEvents); + + // Called by telemetry to retrieve the processed data + RefPtr<UntrustedModulesPromise> GetProcessedData(); + + // Called by IPC actors in the parent process to evaluate module trust + // on behalf of child processes + RefPtr<ModulesTrustPromise> GetModulesTrust(ModulePaths&& aModPaths, + bool aRunAtNormalPriority); + + UntrustedModulesProcessor(const UntrustedModulesProcessor&) = delete; + UntrustedModulesProcessor(UntrustedModulesProcessor&&) = delete; + UntrustedModulesProcessor& operator=(const UntrustedModulesProcessor&) = + delete; + UntrustedModulesProcessor& operator=(UntrustedModulesProcessor&&) = delete; + + private: + ~UntrustedModulesProcessor() = default; + explicit UntrustedModulesProcessor(bool aIsReadyForBackgroundProcessing); + + static bool IsSupportedProcessType(); + + void AddObservers(); + void RemoveObservers(); + + void ScheduleNonEmptyQueueProcessing(const MutexAutoLock& aProofOfLock) + MOZ_REQUIRES(mUnprocessedMutex); + void CancelScheduledProcessing(const MutexAutoLock& aProofOfLock) + MOZ_REQUIRES(mUnprocessedMutex); + void DispatchBackgroundProcessing(); + + void BackgroundProcessModuleLoadQueue(); + void ProcessModuleLoadQueue(); + + // Extract the loading events from mUnprocessedModuleLoads to process and + // move to mProcessedModuleLoads. It's guaranteed that the total length of + // mProcessedModuleLoads will not exceed |aMaxLength|. + UnprocessedModuleLoads ExtractLoadingEventsToProcess(size_t aMaxLength); + + class ModulesMapResultWithLoads final { + public: + ModulesMapResultWithLoads(Maybe<ModulesMapResult>&& aModMapResult, + UnprocessedModuleLoads&& aLoads) + : mModMapResult(std::move(aModMapResult)), mLoads(std::move(aLoads)) {} + Maybe<ModulesMapResult> mModMapResult; + UnprocessedModuleLoads mLoads; + }; + + using GetModulesTrustPromise = + MozPromise<Maybe<ModulesMapResultWithLoads>, nsresult, true>; + + enum class Priority { Default, Background }; + + RefPtr<GetModulesTrustPromise> ProcessModuleLoadQueueChildProcess( + Priority aPriority); + void BackgroundProcessModuleLoadQueueChildProcess(); + + void AssertRunningOnLazyIdleThread(); + + RefPtr<UntrustedModulesPromise> GetProcessedDataInternal(); + RefPtr<UntrustedModulesPromise> GetProcessedDataInternalChildProcess(); + + RefPtr<ModulesTrustPromise> GetModulesTrustInternal( + ModulePaths&& aModPaths, bool aRunAtNormalPriority); + RefPtr<ModulesTrustPromise> GetModulesTrustInternal(ModulePaths&& aModPaths); + + // This function is only called by the parent process + RefPtr<ModuleRecord> GetOrAddModuleRecord(const ModuleEvaluator& aModEval, + const nsAString& aResolvedNtPath); + + // Only called by child processes + RefPtr<ModuleRecord> GetModuleRecord( + const ModulesMap& aModules, + const glue::EnhancedModuleLoadInfo& aModuleLoadInfo); + + RefPtr<GetModulesTrustIpcPromise> SendGetModulesTrust(ModulePaths&& aModules, + Priority aPriority); + + void CompleteProcessing(ModulesMapResultWithLoads&& aModulesAndLoads); + RefPtr<UntrustedModulesPromise> GetAllProcessedData(const char* aSource); + + private: + RefPtr<LazyIdleThread> mThread; + + Mutex mThreadHandleMutex; + Mutex mUnprocessedMutex; + Mutex mModuleCacheMutex; + + // Windows HANDLE for the currently active mThread, if active. + nsAutoHandle mThreadHandle MOZ_GUARDED_BY(mThreadHandleMutex); + + // The members in this group are protected by mUnprocessedMutex + UnprocessedModuleLoads mUnprocessedModuleLoads + MOZ_GUARDED_BY(mUnprocessedMutex); + nsCOMPtr<nsIRunnable> mIdleRunnable MOZ_GUARDED_BY(mUnprocessedMutex); + + // This member must only be touched on mThread + UntrustedModulesData mProcessedModuleLoads; + + enum class Status { StartingUp, Allowed, ShuttingDown }; + + // This member may be touched by any thread + Atomic<Status> mStatus; + + // Cache all module records, including ones trusted and ones loaded in + // child processes, in the browser process to avoid evaluating the same + // module multiple times + ModulesMap mGlobalModuleCache MOZ_GUARDED_BY(mModuleCacheMutex); +}; + +} // namespace mozilla + +#endif // mozilla_UntrustedModulesProcessor_h |