From c0db95d3dda1865d4c6bf0666b0e7439b40b9bf2 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 20:35:44 +0200 Subject: Merging upstream version 115.10.0esr. Signed-off-by: Daniel Baumann --- security/sandbox/linux/SandboxInfo.cpp | 26 +++++-- .../win/src/sandboxbroker/sandboxBroker.cpp | 82 ++++++++++------------ .../sandbox/win/src/sandboxbroker/sandboxBroker.h | 3 +- 3 files changed, 59 insertions(+), 52 deletions(-) (limited to 'security/sandbox') diff --git a/security/sandbox/linux/SandboxInfo.cpp b/security/sandbox/linux/SandboxInfo.cpp index 3d71e55921..aefd9dac2d 100644 --- a/security/sandbox/linux/SandboxInfo.cpp +++ b/security/sandbox/linux/SandboxInfo.cpp @@ -134,11 +134,21 @@ static bool CanCreateUserNamespace() { // the new capabilities (in this case, cloning another namespace) to // detect AppArmor policies that allow CLONE_NEWUSER but don't allow // doing anything useful with it. - pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID, - nullptr, nullptr, nullptr, nullptr); + // + // Bug 1884347: There's a new AppArmor feature which can result in + // unsharing NEWUSER and NEWPID (or NEWNET etc.) in one syscall + // being allowed, but further use of capabilities will be blocked + // afterwards. That may be a bug, but we need to handle it. + pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER, nullptr, nullptr, + nullptr, nullptr); if (pid == 0) { - // In the child. Do as little as possible. - _exit(0); + // The exact meaning of `unshare(CLONE_NEWPID)` is slightly + // counterintuitive but in this case it doesn't matter. This just + // needs to be some operation that attempts to use capabilities, + // to check if it's blocked by an LSM. + int rv = unshare(CLONE_NEWPID); + // Exit with status 0 on success, 1 on failure. + _exit(rv == 0 ? 0 : 1); } if (pid == -1) { // Failure. @@ -149,11 +159,17 @@ static bool CanCreateUserNamespace() { return false; } // Otherwise, in the parent and successful. - bool waitpid_ok = HANDLE_EINTR(waitpid(pid, nullptr, 0)) == pid; + int wstatus; + bool waitpid_ok = HANDLE_EINTR(waitpid(pid, &wstatus, 0)) == pid; MOZ_ASSERT(waitpid_ok); if (!waitpid_ok) { return false; } + // Check for failures reported by the child process. + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { + setenv(kCacheEnvName, "0", 1); + return false; + } setenv(kCacheEnvName, "1", 1); return true; } diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp index bd154d3c78..818c160fed 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -25,11 +25,11 @@ #include "mozilla/StaticPrefs_network.h" #include "mozilla/StaticPrefs_security.h" #include "mozilla/StaticPrefs_widget.h" +#include "mozilla/StaticPtr.h" #include "mozilla/UniquePtr.h" #include "mozilla/Telemetry.h" #include "mozilla/WinDllServices.h" #include "mozilla/WindowsVersion.h" -#include "mozilla/WinHeaderOnlyUtils.h" #include "mozilla/ipc/LaunchError.h" #include "nsAppDirectoryServiceDefs.h" #include "nsCOMPtr.h" @@ -59,11 +59,11 @@ sandbox::BrokerServices* sBrokerService = nullptr; bool SandboxBroker::sRunningFromNetworkDrive = false; // Cached special directories used for adding policy rules. -static UniquePtr sBinDir; -static UniquePtr sProfileDir; -static UniquePtr sLocalAppDataDir; +static StaticAutoPtr sBinDir; +static StaticAutoPtr sProfileDir; +static StaticAutoPtr sLocalAppDataDir; #ifdef ENABLE_SYSTEM_EXTENSION_DIRS -static UniquePtr sUserExtensionsDir; +static StaticAutoPtr sUserExtensionsDir; #endif static LazyLogModule sSandboxBrokerLog("SandboxBroker"); @@ -74,7 +74,7 @@ static LazyLogModule sSandboxBrokerLog("SandboxBroker"); // Used to store whether we have accumulated an error combination for this // session. -static UniquePtr> sLaunchErrors; +static StaticAutoPtr> sLaunchErrors; // This helper function is our version of SandboxWin::AddWin32kLockdownPolicy // of Chromium, making sure the MITIGATION_WIN32K_DISABLE flag is set before @@ -115,15 +115,31 @@ static sandbox::ResultCode AddWin32kLockdownPolicy( return result; } +static void CacheDirAndAutoClear(const nsAString& aDir, + StaticAutoPtr* cacheVar) { + *cacheVar = new nsString(aDir); + ClearOnShutdown(cacheVar); + + // Convert network share path to format for sandbox policy. + if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) { + (*cacheVar)->InsertLiteral(u"??\\UNC", 1); + } +} + /* static */ -void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices) { +void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices, + const nsAString& aBinDir) { sBrokerService = aBrokerServices; sRunningFromNetworkDrive = widget::WinUtils::RunningFromANetworkDrive(); + + if (!aBinDir.IsEmpty()) { + CacheDirAndAutoClear(aBinDir, &sBinDir); + } } static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey, - UniquePtr* cacheVar) { + StaticAutoPtr* cacheVar) { nsCOMPtr dirToCache; nsresult rv = aDirSvc->Get(aDirKey, NS_GET_IID(nsIFile), getter_AddRefs(dirToCache)); @@ -134,14 +150,9 @@ static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey, return; } - *cacheVar = MakeUnique(); - ClearOnShutdown(cacheVar); - MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(**cacheVar)); - - // Convert network share path to format for sandbox policy. - if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) { - (*cacheVar)->InsertLiteral(u"??\\UNC", 1); - } + nsAutoString dirPath; + MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(dirPath)); + CacheDirAndAutoClear(dirPath, cacheVar); } /* static */ @@ -165,7 +176,6 @@ void SandboxBroker::GeckoDependentInitialize() { return; } - CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir); CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir); CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir); #ifdef ENABLE_SYSTEM_EXTENSION_DIRS @@ -176,7 +186,7 @@ void SandboxBroker::GeckoDependentInitialize() { // Create sLaunchErrors up front because ClearOnShutdown must be called on the // main thread. - sLaunchErrors = MakeUnique>(); + sLaunchErrors = new nsTHashtable(); ClearOnShutdown(&sLaunchErrors); } @@ -412,7 +422,7 @@ Result SandboxBroker::LaunchApp( static void AddCachedDirRule(sandbox::TargetPolicy* aPolicy, sandbox::TargetPolicy::Semantics aAccess, - const UniquePtr& aBaseDir, + const StaticAutoPtr& aBaseDir, const nsLiteralString& aRelativePath) { if (!aBaseDir) { // This can only be an NS_WARNING, because it can null for xpcshell tests. @@ -486,35 +496,11 @@ static sandbox::ResultCode AllowProxyLoadFromBinDir( sandbox::TargetPolicy* aPolicy) { // Allow modules in the directory containing the executable such as // mozglue.dll, nss3.dll, etc. - static UniquePtr sInstallDir; - if (!sInstallDir) { - // Since this function can be called before sBinDir is initialized, - // we cache the install path by ourselves. - UniquePtr appDirStr; - if (GetInstallDirectory(appDirStr)) { - sInstallDir = MakeUnique(appDirStr.get()); - sInstallDir->Append(u"\\*"); - - auto setClearOnShutdown = [ptr = &sInstallDir]() -> void { - ClearOnShutdown(ptr); - }; - if (NS_IsMainThread()) { - setClearOnShutdown(); - } else { - SchedulerGroup::Dispatch( - TaskCategory::Other, - NS_NewRunnableFunction("InitSignedPolicyRulesToBypassCig", - std::move(setClearOnShutdown))); - } - } - - if (!sInstallDir) { - return sandbox::SBOX_ERROR_GENERIC; - } - } + nsAutoString rulePath(*sBinDir); + rulePath.Append(u"\\*"_ns); return aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY, sandbox::TargetPolicy::SIGNED_ALLOW_LOAD, - sInstallDir->get()); + rulePath.get()); } static sandbox::ResultCode AddCigToPolicy( @@ -1219,6 +1205,10 @@ void SandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) { sandbox::SBOX_ALL_OK == result, "With these static arguments AddRule should never fail, what happened?"); + // Add rule to allow read access to installation directory. + AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY, + sBinDir, u"\\*"_ns); + // The GPU process needs to write to a shader cache for performance reasons if (sProfileDir) { AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY, diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h index 752fbaa9aa..462e4b4b52 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h @@ -76,7 +76,8 @@ class SandboxBroker : public AbstractSandboxBroker { public: SandboxBroker(); - static void Initialize(sandbox::BrokerServices* aBrokerServices); + static void Initialize(sandbox::BrokerServices* aBrokerServices, + const nsAString& aBinDir); void Shutdown() override {} -- cgit v1.2.3