summaryrefslogtreecommitdiffstats
path: root/security/sandbox
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--security/sandbox/linux/SandboxInfo.cpp26
-rw-r--r--security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp82
-rw-r--r--security/sandbox/win/src/sandboxbroker/sandboxBroker.h3
3 files changed, 59 insertions, 52 deletions
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<nsString> sBinDir;
-static UniquePtr<nsString> sProfileDir;
-static UniquePtr<nsString> sLocalAppDataDir;
+static StaticAutoPtr<nsString> sBinDir;
+static StaticAutoPtr<nsString> sProfileDir;
+static StaticAutoPtr<nsString> sLocalAppDataDir;
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
-static UniquePtr<nsString> sUserExtensionsDir;
+static StaticAutoPtr<nsString> 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<nsTHashtable<nsCStringHashKey>> sLaunchErrors;
+static StaticAutoPtr<nsTHashtable<nsCStringHashKey>> 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<nsString>* 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<nsString>* cacheVar) {
+ StaticAutoPtr<nsString>* cacheVar) {
nsCOMPtr<nsIFile> 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<nsString>();
- 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<nsTHashtable<nsCStringHashKey>>();
+ sLaunchErrors = new nsTHashtable<nsCStringHashKey>();
ClearOnShutdown(&sLaunchErrors);
}
@@ -412,7 +422,7 @@ Result<Ok, mozilla::ipc::LaunchError> SandboxBroker::LaunchApp(
static void AddCachedDirRule(sandbox::TargetPolicy* aPolicy,
sandbox::TargetPolicy::Semantics aAccess,
- const UniquePtr<nsString>& aBaseDir,
+ const StaticAutoPtr<nsString>& 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<nsString> sInstallDir;
- if (!sInstallDir) {
- // Since this function can be called before sBinDir is initialized,
- // we cache the install path by ourselves.
- UniquePtr<wchar_t[]> appDirStr;
- if (GetInstallDirectory(appDirStr)) {
- sInstallDir = MakeUnique<nsString>(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 {}