summaryrefslogtreecommitdiffstats
path: root/toolkit/xre/dllservices/UntrustedModulesProcessor.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
commit9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/xre/dllservices/UntrustedModulesProcessor.h
parentInitial commit. (diff)
downloadthunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.tar.xz
thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--toolkit/xre/dllservices/UntrustedModulesProcessor.h185
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