Bug 1401062 - Avoid doing sandbox-related things to unsandboxed child processes. r=gcp
This is a small piece of cleanup that turned out to not be strictly
necessary for the rest of this, so I've made it a separate commit.
Sandbox-related launch adjustments (currently, interposing libc
functions and providing a file descriptor for the syscall reporter)
are no longer applied to processes that won't be sandboxed. The
MOZ_SANDBOXED environment variable communicates this to the child
process, which allows SandboxEarlyInit to be skipped in that case as
well. The idea is that disabling sandboxing for a process type, as part
of troubleshooting, should disable everything sandbox-related.
As a side-effect, this also skips some very minor but unnecessary
overhead for NPAPI process startup.
MozReview-Commit-ID: D0KxsRIIRN
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -471,16 +471,20 @@ IsLibPresent(const char* aName)
static const Array<const char*, 1> kLibsThatWillCrash {
"libesets_pac.so",
};
#endif // NIGHTLY_BUILD
void
SandboxEarlyInit() {
+ if (PR_GetEnv("MOZ_SANDBOXED") == nullptr) {
+ return;
+ }
+
// If TSYNC is not supported, set up signal handler
// used to enable seccomp on each thread.
if (!SandboxInfo::Get().Test(SandboxInfo::kHasSeccompTSync)) {
// The signal number has to be chosen early, so that the
// interceptions in SandboxHooks.cpp can prevent it from being
// masked.
const int tsyncSignum = FindFreeSignalNumber();
if (tsyncSignum == 0) {
--- a/security/sandbox/linux/SandboxReporterClient.cpp
+++ b/security/sandbox/linux/SandboxReporterClient.cpp
@@ -11,16 +11,17 @@
#include <signal.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include "mozilla/Assertions.h"
#include "mozilla/PodOperations.h"
+#include "prenv.h"
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#ifdef ANDROID
#include "sandbox/linux/system_headers/linux_ucontext.h"
#else
#include <ucontext.h>
#endif
namespace mozilla {
@@ -32,16 +33,22 @@ SandboxReporterClient::SandboxReporterCl
{
// Unfortunately, there isn't a good way to check that the fd is a
// socket connected to the right thing without attempting some kind
// of in-band handshake. However, the crash reporter (which also
// uses a "magic number" fd) doesn't do any kind of checking either,
// so it's probably okay to skip it here.
}
+SandboxReporterClient::SandboxReporterClient(SandboxReport::ProcType aProcType)
+ : SandboxReporterClient(aProcType, kSandboxReporterFileDesc)
+{
+ MOZ_RELEASE_ASSERT(PR_GetEnv("MOZ_SANDBOXED") != nullptr);
+}
+
SandboxReport
SandboxReporterClient::MakeReport(const void* aContext)
{
SandboxReport report;
const auto ctx = static_cast<const ucontext_t*>(aContext);
// Zero the entire struct; some memory safety analyses care about
// sending uninitialized alignment padding to another process.
--- a/security/sandbox/linux/SandboxReporterClient.h
+++ b/security/sandbox/linux/SandboxReporterClient.h
@@ -14,18 +14,21 @@ namespace mozilla {
// This class is instantiated in child processes in Sandbox.cpp to
// send reports from the SIGSYS handler to the SandboxReporter
// instance in the parent.
class SandboxReporterClient {
public:
// Note: this does not take ownership of the file descriptor; if
// it's not kSandboxReporterFileDesc (e.g., for unit testing), the
// caller will need to close it to avoid leaks.
- explicit SandboxReporterClient(SandboxReport::ProcType aProcType,
- int aFd = kSandboxReporterFileDesc);
+ SandboxReporterClient(SandboxReport::ProcType aProcType, int aFd);
+
+ // This constructor uses the default fd (kSandboxReporterFileDesc)
+ // for a sandboxed child process.
+ explicit SandboxReporterClient(SandboxReport::ProcType aProcType);
// Constructs a report from a signal context (the ucontext_t* passed
// as void* to an sa_sigaction handler); uses the caller's pid and tid.
SandboxReport MakeReport(const void* aContext);
void SendReport(const SandboxReport& aReport);
SandboxReport MakeReportAndSend(const void* aContext) {
--- a/security/sandbox/linux/launch/SandboxLaunch.cpp
+++ b/security/sandbox/linux/launch/SandboxLaunch.cpp
@@ -110,32 +110,36 @@ GetEffectiveSandboxLevel(GeckoProcessTyp
return 0;
}
}
void
SandboxLaunchPrepare(GeckoProcessType aType,
base::LaunchOptions* aOptions)
{
- PreloadSandboxLib(&aOptions->env_map);
- AttachSandboxReporter(&aOptions->fds_to_remap);
-
auto info = SandboxInfo::Get();
// We won't try any kind of sandboxing without seccomp-bpf.
if (!info.Test(SandboxInfo::kHasSeccompBPF)) {
return;
}
// Check prefs (and env vars) controlling sandbox use.
int level = GetEffectiveSandboxLevel(aType);
if (level == 0) {
return;
}
+ // At this point, we know we'll be using sandboxing; generic
+ // sandboxing support goes here. The MOZ_SANDBOXED env var tells
+ // the child process whether this is the case.
+ aOptions->env_map["MOZ_SANDBOXED"] = "1";
+ PreloadSandboxLib(&aOptions->env_map);
+ AttachSandboxReporter(&aOptions->fds_to_remap);
+
// Anything below this requires unprivileged user namespaces.
if (!info.Test(SandboxInfo::kHasUserNamespaces)) {
return;
}
bool canChroot = false;
int flags = 0;