mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 13:56:29 +00:00
Bug 1710625 - SandboxTest with SocketProcess r=necko-reviewers,handyman,jld,kershaw
Differential Revision: https://phabricator.services.mozilla.com/D114861
This commit is contained in:
parent
07973852a6
commit
6b5f586e94
@ -21,6 +21,10 @@ include protocol PProxyConfigLookup;
|
||||
include protocol PNativeDNSResolverOverride;
|
||||
include protocol PRemoteLazyInputStream;
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
include protocol PSandboxTesting;
|
||||
#endif
|
||||
|
||||
include MemoryReportTypes;
|
||||
include NeckoChannelParams;
|
||||
include PrefsTypes;
|
||||
@ -143,6 +147,9 @@ child:
|
||||
async InitLinuxSandbox(FileDescriptor? sandboxBroker);
|
||||
async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
|
||||
async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
async InitSandboxTesting(Endpoint<PSandboxTestingChild> aEndpoint);
|
||||
#endif
|
||||
// test-only
|
||||
async SocketProcessTelemetryPing();
|
||||
|
||||
|
@ -61,6 +61,10 @@
|
||||
# include "mozilla/net/WebrtcTCPSocketChild.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
# include "mozilla/SandboxTestingChild.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -275,6 +279,17 @@ mozilla::ipc::IPCResult SocketProcessChild::RecvInitProfiler(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
mozilla::ipc::IPCResult SocketProcessChild::RecvInitSandboxTesting(
|
||||
Endpoint<PSandboxTestingChild>&& aEndpoint) {
|
||||
if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
|
||||
return IPC_FAIL(
|
||||
this, "InitSandboxTesting failed to initialise the child process.");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
#endif
|
||||
|
||||
mozilla::ipc::IPCResult SocketProcessChild::RecvSocketProcessTelemetryPing() {
|
||||
const uint32_t kExpectedUintValue = 42;
|
||||
Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_SOCKET_ONLY_UINT,
|
||||
|
@ -56,6 +56,10 @@ class SocketProcessChild final
|
||||
Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint);
|
||||
mozilla::ipc::IPCResult RecvInitProfiler(
|
||||
Endpoint<mozilla::PProfilerChild>&& aEndpoint);
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
|
||||
mozilla::ipc::IPCResult RecvInitSandboxTesting(
|
||||
Endpoint<PSandboxTestingChild>&& aEndpoint);
|
||||
#endif
|
||||
mozilla::ipc::IPCResult RecvSocketProcessTelemetryPing();
|
||||
|
||||
PWebrtcTCPSocketChild* AllocPWebrtcTCPSocketChild(const Maybe<TabId>& tabId);
|
||||
|
@ -56,6 +56,7 @@ UNIFIED_SOURCES += [
|
||||
|
||||
PREPROCESSED_IPDL_SOURCES += [
|
||||
"PNecko.ipdl",
|
||||
"PSocketProcess.ipdl",
|
||||
]
|
||||
|
||||
IPDL_SOURCES = [
|
||||
@ -66,7 +67,6 @@ IPDL_SOURCES = [
|
||||
"PInputChannelThrottleQueue.ipdl",
|
||||
"PProxyConfigLookup.ipdl",
|
||||
"PSimpleChannel.ipdl",
|
||||
"PSocketProcess.ipdl",
|
||||
"PSocketProcessBridge.ipdl",
|
||||
]
|
||||
|
||||
|
@ -41,6 +41,10 @@ if CONFIG["MOZ_SANDBOX"] and CONFIG["MOZ_DEBUG"] and CONFIG["ENABLE_TESTS"]:
|
||||
"test/mozISandboxTest.idl",
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/netwerk/base",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
@ -7,12 +7,15 @@
|
||||
#include "SandboxTest.h"
|
||||
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "SandboxTestingParent.h"
|
||||
#include "SandboxTestingChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/gfx/GPUProcessManager.h"
|
||||
#include "mozilla/gfx/GPUChild.h"
|
||||
#include "mozilla/net/SocketProcessParent.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "nsIOService.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
@ -84,6 +87,40 @@ SandboxTest::StartTests(const nsTArray<nsCString>& aProcessesList) {
|
||||
break;
|
||||
}
|
||||
|
||||
case GeckoProcessType_Socket: {
|
||||
// mochitest harness force this variable, but we actually do not want
|
||||
// that
|
||||
int rv_unset =
|
||||
#ifdef XP_UNIX
|
||||
unsetenv("MOZ_DISABLE_SOCKET_PROCESS");
|
||||
#endif // XP_UNIX
|
||||
#ifdef XP_WIN
|
||||
_putenv("MOZ_DISABLE_SOCKET_PROCESS=");
|
||||
#endif // XP_WIN
|
||||
MOZ_ASSERT(rv_unset == 0, "Error unsetting env var");
|
||||
|
||||
nsresult rv_pref =
|
||||
Preferences::SetBool("network.process.enabled", true);
|
||||
MOZ_ASSERT(rv_pref == NS_OK, "Error enforcing pref");
|
||||
|
||||
MOZ_ASSERT(net::gIOService, "No gIOService?");
|
||||
RefPtr<SandboxTest> self = this;
|
||||
net::gIOService->CallOrWaitForSocketProcess([self, type]() {
|
||||
// If socket process was previously disabled by env,
|
||||
// nsIOService code will take some time before it creates the new
|
||||
// process and it triggers this callback
|
||||
//
|
||||
// If that happens, then by the time we reach the end of StartTests()
|
||||
// the mSandboxTestingParents[type] might not yet have been updated
|
||||
// this is why below we allow for a delayed dispatch to give a chance
|
||||
net::SocketProcessParent* parent =
|
||||
net::SocketProcessParent::GetSingleton();
|
||||
self->mSandboxTestingParents[type] =
|
||||
InitializeSandboxTestingActors(parent);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"SandboxTest does not yet support this process type");
|
||||
@ -91,7 +128,24 @@ SandboxTest::StartTests(const nsTArray<nsCString>& aProcessesList) {
|
||||
}
|
||||
|
||||
if (!mSandboxTestingParents[type]) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (type == GeckoProcessType_Socket) {
|
||||
// Give a chance to the socket process to be present and to the callback
|
||||
// above to be ran. We delay by 5 seconds, but hopefully since it is all
|
||||
// on the main thread, the value itself should not be important.
|
||||
RefPtr<SandboxTest> self = this;
|
||||
NS_DelayedDispatchToCurrentThread(
|
||||
NS_NewRunnableFunction(
|
||||
"SandboxTest::StartTests",
|
||||
[self, type]() {
|
||||
if (!self->mSandboxTestingParents[type]) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"SandboxTest failed to get a Parent");
|
||||
}
|
||||
}),
|
||||
5e3 /* delay by five seconds */);
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -5,18 +5,15 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SandboxTestingChild.h"
|
||||
#include "SandboxTestingChildTests.h"
|
||||
#include "SandboxTestingThread.h"
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#ifdef XP_UNIX
|
||||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <time.h>
|
||||
# include <unistd.h>
|
||||
#ifdef XP_LINUX
|
||||
# include "mozilla/Sandbox.h"
|
||||
#endif
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
SandboxTestingChild* SandboxTestingChild::sInstance = nullptr;
|
||||
@ -61,37 +58,22 @@ void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
|
||||
DebugOnly<bool> ok = aEndpoint.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
|
||||
#ifdef XP_LINUX
|
||||
bool sandboxCrashOnError = SetSandboxCrashOnError(false);
|
||||
#endif
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
#ifdef XP_UNIX
|
||||
struct stat st;
|
||||
static const char kAllowedPath[] = "/usr/lib";
|
||||
|
||||
ErrnoTest("fstatat_as_stat"_ns, true,
|
||||
[&] { return fstatat(AT_FDCWD, kAllowedPath, &st, 0); });
|
||||
ErrnoTest("fstatat_as_lstat"_ns, true, [&] {
|
||||
return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW);
|
||||
});
|
||||
|
||||
# ifdef XP_LINUX
|
||||
ErrnoTest("fstatat_as_fstat"_ns, true,
|
||||
[&] { return fstatat(0, "", &st, AT_EMPTY_PATH); });
|
||||
# endif // XP_LINUX
|
||||
|
||||
const struct timespec usec = {0, 1000};
|
||||
ErrnoTest("nanosleep"_ns, true, [&] { return nanosleep(&usec, nullptr); });
|
||||
|
||||
struct timespec res = {0, 0};
|
||||
ErrnoTest("clock_getres"_ns, true,
|
||||
[&] { return clock_getres(CLOCK_REALTIME, &res); });
|
||||
|
||||
#else // XP_UNIX
|
||||
SendReportTestResults("dummy_test"_ns,
|
||||
/* shouldSucceed */ true,
|
||||
/* didSucceed */ true,
|
||||
"The test framework fails if there are no cases."_ns);
|
||||
#endif // XP_UNIX
|
||||
RunTestsContent(this);
|
||||
}
|
||||
|
||||
if (XRE_IsSocketProcess()) {
|
||||
RunTestsSocket(this);
|
||||
}
|
||||
|
||||
#ifdef XP_LINUX
|
||||
SetSandboxCrashOnError(sandboxCrashOnError);
|
||||
#endif
|
||||
|
||||
// Tell SandboxTest that this process is done with all tests.
|
||||
SendTestCompleted();
|
||||
}
|
||||
|
@ -40,11 +40,6 @@ class SandboxTestingChild : public PSandboxTestingChild {
|
||||
|
||||
virtual bool RecvShutDown();
|
||||
|
||||
private:
|
||||
explicit SandboxTestingChild(SandboxTestingThread* aThread,
|
||||
Endpoint<PSandboxTestingChild>&& aEndpoint);
|
||||
void Bind(Endpoint<PSandboxTestingChild>&& aEndpoint);
|
||||
|
||||
#ifdef XP_UNIX
|
||||
// For test cases that return an error number or 0, like newer POSIX APIs.
|
||||
void PosixTest(const nsCString& aName, bool aExpectSuccess, int aStatus);
|
||||
@ -56,6 +51,11 @@ class SandboxTestingChild : public PSandboxTestingChild {
|
||||
void ErrnoTest(const nsCString& aName, bool aExpectSuccess, F&& aFunction);
|
||||
#endif
|
||||
|
||||
private:
|
||||
explicit SandboxTestingChild(SandboxTestingThread* aThread,
|
||||
Endpoint<PSandboxTestingChild>&& aEndpoint);
|
||||
void Bind(Endpoint<PSandboxTestingChild>&& aEndpoint);
|
||||
|
||||
UniquePtr<SandboxTestingThread> mThread;
|
||||
|
||||
static SandboxTestingChild* sInstance;
|
||||
|
95
security/sandbox/common/test/SandboxTestingChildTests.h
Normal file
95
security/sandbox/common/test/SandboxTestingChildTests.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* -*- 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SandboxTestingChild.h"
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#ifdef XP_UNIX
|
||||
# include <fcntl.h>
|
||||
# include <netdb.h>
|
||||
# ifdef XP_LINUX
|
||||
# include <sys/prctl.h>
|
||||
# endif // XP_LINUX
|
||||
# include <sys/socket.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <time.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void RunTestsContent(SandboxTestingChild* child) {
|
||||
MOZ_ASSERT(child, "No SandboxTestingChild*?");
|
||||
|
||||
#ifdef XP_UNIX
|
||||
struct stat st;
|
||||
static const char kAllowedPath[] = "/usr/lib";
|
||||
|
||||
child->ErrnoTest("fstatat_as_stat"_ns, true,
|
||||
[&] { return fstatat(AT_FDCWD, kAllowedPath, &st, 0); });
|
||||
child->ErrnoTest("fstatat_as_lstat"_ns, true, [&] {
|
||||
return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW);
|
||||
});
|
||||
|
||||
# ifdef XP_LINUX
|
||||
child->ErrnoTest("fstatat_as_fstat"_ns, true,
|
||||
[&] { return fstatat(0, "", &st, AT_EMPTY_PATH); });
|
||||
# endif // XP_LINUX
|
||||
|
||||
const struct timespec usec = {0, 1000};
|
||||
child->ErrnoTest("nanosleep"_ns, true,
|
||||
[&] { return nanosleep(&usec, nullptr); });
|
||||
|
||||
struct timespec res = {0, 0};
|
||||
child->ErrnoTest("clock_getres"_ns, true,
|
||||
[&] { return clock_getres(CLOCK_REALTIME, &res); });
|
||||
|
||||
#else // XP_UNIX
|
||||
child->SendReportTestResults(
|
||||
"dummy_test"_ns,
|
||||
/* shouldSucceed */ true,
|
||||
/* didSucceed */ true,
|
||||
"The test framework fails if there are no cases."_ns);
|
||||
#endif // XP_UNIX
|
||||
}
|
||||
|
||||
void RunTestsSocket(SandboxTestingChild* child) {
|
||||
MOZ_ASSERT(child, "No SandboxTestingChild*?");
|
||||
|
||||
#ifdef XP_UNIX
|
||||
child->ErrnoTest("getaddrinfo"_ns, true, [&] {
|
||||
struct addrinfo* res;
|
||||
int rv = getaddrinfo("localhost", nullptr, nullptr, &res);
|
||||
if (res != nullptr) {
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
return rv;
|
||||
});
|
||||
|
||||
# ifdef XP_LINUX
|
||||
child->ErrnoTest("prctl_allowed"_ns, true, [&] {
|
||||
int rv = prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
|
||||
return rv;
|
||||
});
|
||||
|
||||
child->ErrnoTest("prctl_blocked"_ns, false, [&] {
|
||||
int rv = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
|
||||
return rv;
|
||||
});
|
||||
# endif // XP_LINUX
|
||||
|
||||
#else // XP_UNIX
|
||||
child->SendReportTestResults(
|
||||
"dummy_test"_ns,
|
||||
/* shouldSucceed */ true,
|
||||
/* didSucceed */ true,
|
||||
"The test framework fails if there are no cases."_ns);
|
||||
#endif // XP_UNIX
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -83,7 +83,7 @@ mozilla::Atomic<int> gSeccompTsyncBroadcastSignum(0);
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static bool gSandboxCrashOnError = false;
|
||||
static mozilla::Atomic<bool> gSandboxCrashOnError(false);
|
||||
|
||||
// This is initialized by SandboxSetCrashFunc().
|
||||
SandboxCrashFunc gSandboxCrashFunc;
|
||||
@ -709,4 +709,10 @@ void SetSocketProcessSandbox(int aBroker) {
|
||||
SetCurrentProcessSandbox(GetSocketProcessSandboxPolicy(sBroker));
|
||||
}
|
||||
|
||||
bool SetSandboxCrashOnError(bool aValue) {
|
||||
bool oldValue = gSandboxCrashOnError;
|
||||
gSandboxCrashOnError = aValue;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -63,6 +63,10 @@ MOZ_EXPORT void SetRemoteDataDecoderSandbox(int aBroker);
|
||||
|
||||
MOZ_EXPORT void SetSocketProcessSandbox(int aBroker);
|
||||
|
||||
// We want to turn on/off crashing on error when running some tests
|
||||
// This will return current value and set the aValue we pass
|
||||
MOZ_EXPORT bool SetSandboxCrashOnError(bool aValue);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_Sandbox_h
|
||||
|
@ -11,7 +11,10 @@ function test() {
|
||||
);
|
||||
|
||||
// Types of processes to test, taken from GeckoProcessTypes.h
|
||||
var processTypes = ["tab", "gpu"];
|
||||
// GPU process might not run depending on the platform, so we need it to be
|
||||
// the last one of the list to allow the remainingTests logic below to work
|
||||
// as expected.
|
||||
var processTypes = ["tab", "socket", "gpu"];
|
||||
|
||||
// A callback called after each test-result.
|
||||
Services.obs.addObserver(function result(subject, topic, data) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user