Bug 1839834 - Allow per-sandbox disabling on Utility r=jld

Differential Revision: https://phabricator.services.mozilla.com/D181782
This commit is contained in:
Alexandre Lissy 2023-06-27 13:10:14 +00:00
parent bef38031b7
commit a9ee883ccf
11 changed files with 144 additions and 12 deletions

View file

@ -91,6 +91,7 @@
#endif #endif
#include "mozilla/ipc/UtilityProcessHost.h" #include "mozilla/ipc/UtilityProcessHost.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "nsClassHashtable.h" #include "nsClassHashtable.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
@ -634,7 +635,7 @@ void GeckoChildProcessHost::PrepareLaunch() {
} }
#if defined(XP_LINUX) && defined(MOZ_SANDBOX) #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
SandboxLaunchPrepare(mProcessType, mLaunchOptions.get()); SandboxLaunchPrepare(mProcessType, mLaunchOptions.get(), mSandbox);
#endif #endif
#ifdef XP_WIN #ifdef XP_WIN
@ -1524,7 +1525,7 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
} }
break; break;
case GeckoProcessType_Utility: case GeckoProcessType_Utility:
if (!PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX")) { if (IsUtilitySandboxEnabled(mSandbox)) {
if (!mResults.mSandboxBroker->SetSecurityLevelForUtilityProcess( if (!mResults.mSandboxBroker->SetSecurityLevelForUtilityProcess(
mSandbox)) { mSandbox)) {
return Err(LaunchError("SetSecurityLevelForUtilityProcess")); return Err(LaunchError("SetSecurityLevelForUtilityProcess"));

View file

@ -9,6 +9,7 @@
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/UtilityProcessManager.h" #include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "chrome/common/process_watcher.h" #include "chrome/common/process_watcher.h"
@ -52,8 +53,7 @@ UtilityProcessHost::UtilityProcessHost(SandboxingKind aSandbox,
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
if (!sLaunchWithMacSandbox) { if (!sLaunchWithMacSandbox) {
sLaunchWithMacSandbox = sLaunchWithMacSandbox = IsUtilitySandboxEnabled(aSandbox);
(PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX") == nullptr);
} }
mDisableOSActivityMode = sLaunchWithMacSandbox; mDisableOSActivityMode = sLaunchWithMacSandbox;
#endif #endif

View file

@ -0,0 +1,55 @@
/* -*- 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 http://mozilla.org/MPL/2.0/. */
#include "UtilityProcessSandboxing.h"
#include <vector>
#include <string>
#include "prenv.h"
namespace mozilla::ipc {
std::vector<std::string> split(const std::string& str, char s) {
std::vector<std::string> rv;
size_t last = 0;
size_t i;
size_t c = str.size();
for (i = 0; i <= c; ++i) {
if (i == c || str[i] == s) {
rv.push_back(str.substr(last, i - last));
last = i + 1;
}
}
return rv;
}
bool IsUtilitySandboxEnabled(const char* envVar, SandboxingKind aKind) {
if (envVar == nullptr) {
return true;
}
const std::string disableUtility(envVar);
if (disableUtility == "1") {
return false;
}
std::vector<std::string> components = split(disableUtility, ',');
const std::string thisKind = "utility:" + std::to_string(aKind);
for (const std::string& thisOne : components) {
if (thisOne == thisKind) {
return false;
}
}
return true;
}
bool IsUtilitySandboxEnabled(SandboxingKind aKind) {
return IsUtilitySandboxEnabled(PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX"),
aKind);
}
} // namespace mozilla::ipc

View file

@ -35,6 +35,9 @@ enum SandboxingKind : uint64_t {
}; };
bool IsUtilitySandboxEnabled(const char* envVar, SandboxingKind aKind);
bool IsUtilitySandboxEnabled(SandboxingKind aKind);
} // namespace ipc } // namespace ipc
} // namespace mozilla } // namespace mozilla

View file

@ -201,6 +201,7 @@ UNIFIED_SOURCES += [
"UtilityProcessImpl.cpp", "UtilityProcessImpl.cpp",
"UtilityProcessManager.cpp", "UtilityProcessManager.cpp",
"UtilityProcessParent.cpp", "UtilityProcessParent.cpp",
"UtilityProcessSandboxing.cpp",
] ]
SOURCES += [ SOURCES += [

View file

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/gtest/MozHelpers.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
using namespace mozilla;
using namespace mozilla::ipc;
TEST(UtilityProcessSandboxing, ParseNoEnvVar)
{ EXPECT_TRUE(IsUtilitySandboxEnabled("", SandboxingKind::COUNT)); }
TEST(UtilityProcessSandboxing, ParseEnvVar_DisableAll)
{ EXPECT_FALSE(IsUtilitySandboxEnabled("1", SandboxingKind::COUNT)); }
TEST(UtilityProcessSandboxing, ParseEnvVar_DontDisableAll)
{ EXPECT_TRUE(IsUtilitySandboxEnabled("0", SandboxingKind::COUNT)); }
TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly)
{
EXPECT_FALSE(
IsUtilitySandboxEnabled("utility:0", SandboxingKind::GENERIC_UTILITY));
EXPECT_TRUE(IsUtilitySandboxEnabled("utility:0", SandboxingKind::COUNT));
}
#if defined(XP_DARWIN)
TEST(UtilityProcessSandboxing, ParseEnvVar_DisableAppleAudioOnly)
{
EXPECT_FALSE(IsUtilitySandboxEnabled(
"utility:1", SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA));
EXPECT_TRUE(
IsUtilitySandboxEnabled("utility:1", SandboxingKind::GENERIC_UTILITY));
}
#endif // defined(XP_DARWIN)
#if defined(XP_WIN)
TEST(UtilityProcessSandboxing, ParseEnvVar_DisableWMFOnly)
{
EXPECT_FALSE(IsUtilitySandboxEnabled(
"utility:1", SandboxingKind::UTILITY_AUDIO_DECODING_WMF));
EXPECT_TRUE(
IsUtilitySandboxEnabled("utility:1", SandboxingKind::GENERIC_UTILITY));
}
#endif // defined(XP_WIN)
TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly_Multiples)
{
EXPECT_FALSE(IsUtilitySandboxEnabled("utility:1,utility:0,utility:2",
SandboxingKind::GENERIC_UTILITY));
#if defined(XP_DARWIN)
EXPECT_FALSE(IsUtilitySandboxEnabled(
"utility:1,utility:0,utility:2",
SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA));
#endif // XP_DARWIN
#if defined(XP_WIN)
EXPECT_FALSE(
IsUtilitySandboxEnabled("utility:1,utility:0,utility:2",
SandboxingKind::UTILITY_AUDIO_DECODING_WMF));
#endif // XP_WIN
EXPECT_TRUE(IsUtilitySandboxEnabled("utility:8,utility:0,utility:6",
SandboxingKind::COUNT));
}

View file

@ -9,6 +9,7 @@ Library("ipcgluetest")
UNIFIED_SOURCES = [ UNIFIED_SOURCES = [
"TestAsyncBlockers.cpp", "TestAsyncBlockers.cpp",
"TestUtilityProcess.cpp", "TestUtilityProcess.cpp",
"TestUtilityProcessSandboxing.cpp",
] ]
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [

View file

@ -43,6 +43,7 @@
#include "mozilla/Span.h" #include "mozilla/Span.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "prenv.h" #include "prenv.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
@ -733,7 +734,7 @@ void SetSocketProcessSandbox(int aBroker) {
void SetUtilitySandbox(int aBroker, ipc::SandboxingKind aKind) { void SetUtilitySandbox(int aBroker, ipc::SandboxingKind aKind) {
if (!SandboxInfo::Get().Test(SandboxInfo::kHasSeccompBPF) || if (!SandboxInfo::Get().Test(SandboxInfo::kHasSeccompBPF) ||
PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX")) { !IsUtilitySandboxEnabled(aKind)) {
if (aBroker >= 0) { if (aBroker >= 0) {
close(aBroker); close(aBroker);
} }

View file

@ -35,6 +35,7 @@
#include "mozilla/StaticPrefs_media.h" #include "mozilla/StaticPrefs_media.h"
#include "mozilla/StaticPrefs_security.h" #include "mozilla/StaticPrefs_security.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsIGfxInfo.h" #include "nsIGfxInfo.h"
@ -238,7 +239,8 @@ class SandboxFork : public base::LaunchOptions::ForkDelegate {
SandboxFork& operator=(const SandboxFork&) = delete; SandboxFork& operator=(const SandboxFork&) = delete;
}; };
static int GetEffectiveSandboxLevel(GeckoProcessType aType) { static int GetEffectiveSandboxLevel(GeckoProcessType aType,
ipc::SandboxingKind aKind) {
auto info = SandboxInfo::Get(); auto info = SandboxInfo::Get();
switch (aType) { switch (aType) {
case GeckoProcessType_GMPlugin: case GeckoProcessType_GMPlugin:
@ -266,14 +268,14 @@ static int GetEffectiveSandboxLevel(GeckoProcessType aType) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
return GetEffectiveSocketProcessSandboxLevel(); return GetEffectiveSocketProcessSandboxLevel();
case GeckoProcessType_Utility: case GeckoProcessType_Utility:
return PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX") == nullptr ? 1 : 0; return IsUtilitySandboxEnabled(aKind);
default: default:
return 0; return 0;
} }
} }
void SandboxLaunchPrepare(GeckoProcessType aType, void SandboxLaunchPrepare(GeckoProcessType aType, base::LaunchOptions* aOptions,
base::LaunchOptions* aOptions) { ipc::SandboxingKind aKind) {
auto info = SandboxInfo::Get(); auto info = SandboxInfo::Get();
// We won't try any kind of sandboxing without seccomp-bpf. // We won't try any kind of sandboxing without seccomp-bpf.
@ -282,7 +284,7 @@ void SandboxLaunchPrepare(GeckoProcessType aType,
} }
// Check prefs (and env vars) controlling sandbox use. // Check prefs (and env vars) controlling sandbox use.
int level = GetEffectiveSandboxLevel(aType); int level = GetEffectiveSandboxLevel(aType, aKind);
if (level == 0) { if (level == 0) {
return; return;
} }

View file

@ -8,6 +8,7 @@
#define mozilla_SandboxLaunch_h #define mozilla_SandboxLaunch_h
#include "base/process_util.h" #include "base/process_util.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include <vector> #include <vector>
@ -16,8 +17,8 @@ namespace mozilla {
// Called in the parent process to set up launch-time aspects of // Called in the parent process to set up launch-time aspects of
// sandboxing. If aType is GeckoProcessType_Content, this must be // sandboxing. If aType is GeckoProcessType_Content, this must be
// called on the main thread in order to access prefs. // called on the main thread in order to access prefs.
void SandboxLaunchPrepare(GeckoProcessType aType, void SandboxLaunchPrepare(GeckoProcessType aType, base::LaunchOptions* aOptions,
base::LaunchOptions* aOptions); ipc::SandboxingKind aKind);
#if defined(MOZ_ENABLE_FORKSERVER) #if defined(MOZ_ENABLE_FORKSERVER)
void SandboxLaunchForkServerPrepare(const std::vector<std::string>& aArgv, void SandboxLaunchForkServerPrepare(const std::vector<std::string>& aArgv,
base::LaunchOptions& aOptions); base::LaunchOptions& aOptions);

View file

@ -72,6 +72,7 @@ UNIFIED_SOURCES += [
"../chromium/sandbox/linux/bpf_dsl/syscall_set.cc", "../chromium/sandbox/linux/bpf_dsl/syscall_set.cc",
"../chromium/sandbox/linux/seccomp-bpf/die.cc", "../chromium/sandbox/linux/seccomp-bpf/die.cc",
"../chromium/sandbox/linux/seccomp-bpf/syscall.cc", "../chromium/sandbox/linux/seccomp-bpf/syscall.cc",
"/ipc/glue/UtilityProcessSandboxing.cpp",
"broker/SandboxBrokerCommon.cpp", "broker/SandboxBrokerCommon.cpp",
"Sandbox.cpp", "Sandbox.cpp",
"SandboxBrokerClient.cpp", "SandboxBrokerClient.cpp",