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

View file

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

View file

@ -201,6 +201,7 @@ UNIFIED_SOURCES += [
"UtilityProcessImpl.cpp",
"UtilityProcessManager.cpp",
"UtilityProcessParent.cpp",
"UtilityProcessSandboxing.cpp",
]
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 = [
"TestAsyncBlockers.cpp",
"TestUtilityProcess.cpp",
"TestUtilityProcessSandboxing.cpp",
]
LOCAL_INCLUDES += [

View file

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

View file

@ -35,6 +35,7 @@
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/StaticPrefs_security.h"
#include "mozilla/Unused.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsIGfxInfo.h"
@ -238,7 +239,8 @@ class SandboxFork : public base::LaunchOptions::ForkDelegate {
SandboxFork& operator=(const SandboxFork&) = delete;
};
static int GetEffectiveSandboxLevel(GeckoProcessType aType) {
static int GetEffectiveSandboxLevel(GeckoProcessType aType,
ipc::SandboxingKind aKind) {
auto info = SandboxInfo::Get();
switch (aType) {
case GeckoProcessType_GMPlugin:
@ -266,14 +268,14 @@ static int GetEffectiveSandboxLevel(GeckoProcessType aType) {
MOZ_ASSERT(NS_IsMainThread());
return GetEffectiveSocketProcessSandboxLevel();
case GeckoProcessType_Utility:
return PR_GetEnv("MOZ_DISABLE_UTILITY_SANDBOX") == nullptr ? 1 : 0;
return IsUtilitySandboxEnabled(aKind);
default:
return 0;
}
}
void SandboxLaunchPrepare(GeckoProcessType aType,
base::LaunchOptions* aOptions) {
void SandboxLaunchPrepare(GeckoProcessType aType, base::LaunchOptions* aOptions,
ipc::SandboxingKind aKind) {
auto info = SandboxInfo::Get();
// 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.
int level = GetEffectiveSandboxLevel(aType);
int level = GetEffectiveSandboxLevel(aType, aKind);
if (level == 0) {
return;
}

View file

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

View file

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