summaryrefslogtreecommitdiffstats
path: root/security/sandbox/common/test/SandboxTestingChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/common/test/SandboxTestingChild.cpp')
-rw-r--r--security/sandbox/common/test/SandboxTestingChild.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/security/sandbox/common/test/SandboxTestingChild.cpp b/security/sandbox/common/test/SandboxTestingChild.cpp
new file mode 100644
index 0000000000..3a9d61556c
--- /dev/null
+++ b/security/sandbox/common/test/SandboxTestingChild.cpp
@@ -0,0 +1,194 @@
+/* -*- 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 "SandboxTestingChildTests.h"
+#include "SandboxTestingThread.h"
+#include "mozilla/ipc/Endpoint.h"
+#include "mozilla/ipc/UtilityProcessSandboxing.h"
+#include "mozilla/ipc/UtilityProcessChild.h"
+
+#ifdef XP_LINUX
+# include "mozilla/Sandbox.h"
+#endif
+
+#include "nsXULAppAPI.h"
+
+namespace mozilla {
+
+StaticRefPtr<SandboxTestingChild> SandboxTestingChild::sInstance;
+
+bool SandboxTestingChild::IsTestThread() { return mThread->IsOnThread(); }
+
+void SandboxTestingChild::PostToTestThread(
+ already_AddRefed<nsIRunnable>&& runnable) {
+ mThread->Dispatch(std::move(runnable));
+}
+
+/* static */
+bool SandboxTestingChild::Initialize(
+ Endpoint<PSandboxTestingChild>&& aSandboxTestingEndpoint) {
+ MOZ_ASSERT(!sInstance);
+ SandboxTestingThread* thread = SandboxTestingThread::Create();
+ if (!thread) {
+ return false;
+ }
+ sInstance =
+ new SandboxTestingChild(thread, std::move(aSandboxTestingEndpoint));
+ thread->Dispatch(NewRunnableMethod<Endpoint<PSandboxTestingChild>&&>(
+ "SandboxTestingChild::Bind", sInstance.get(), &SandboxTestingChild::Bind,
+ std::move(aSandboxTestingEndpoint)));
+ return true;
+}
+
+/* static */
+SandboxTestingChild* SandboxTestingChild::GetInstance() {
+ MOZ_ASSERT(sInstance, "Must initialize SandboxTestingChild before using it");
+ return sInstance;
+}
+
+SandboxTestingChild::SandboxTestingChild(
+ SandboxTestingThread* aThread, Endpoint<PSandboxTestingChild>&& aEndpoint)
+ : mThread(aThread) {}
+
+SandboxTestingChild::~SandboxTestingChild() = default;
+
+void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
+ MOZ_RELEASE_ASSERT(mThread->IsOnThread());
+ DebugOnly<bool> ok = aEndpoint.Bind(this);
+ MOZ_ASSERT(ok);
+
+#ifdef XP_LINUX
+ bool sandboxCrashOnError = SetSandboxCrashOnError(false);
+#endif
+
+ if (XRE_IsContentProcess()) {
+ RunTestsContent(this);
+ }
+
+ if (XRE_IsRDDProcess()) {
+ RunTestsRDD(this);
+ }
+
+ if (XRE_IsGMPluginProcess()) {
+ RunTestsGMPlugin(this);
+ }
+
+ if (XRE_IsSocketProcess()) {
+ RunTestsSocket(this);
+ }
+
+ if (XRE_IsGPUProcess()) {
+ RunTestsGPU(this);
+ }
+
+ if (XRE_IsUtilityProcess()) {
+ RefPtr<ipc::UtilityProcessChild> s = ipc::UtilityProcessChild::Get();
+ MOZ_ASSERT(s, "Unable to grab a UtilityProcessChild");
+ switch (s->mSandbox) {
+ case ipc::SandboxingKind::GENERIC_UTILITY:
+ RunTestsGenericUtility(this);
+#ifdef MOZ_APPLEMEDIA
+ [[fallthrough]];
+ case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA:
+#endif
+#ifdef XP_WIN
+ [[fallthrough]];
+ case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
+#endif
+ RunTestsUtilityAudioDecoder(this, s->mSandbox);
+ break;
+
+ default:
+ MOZ_ASSERT(false, "Invalid SandboxingKind");
+ break;
+ }
+ }
+
+#ifdef XP_LINUX
+ SetSandboxCrashOnError(sandboxCrashOnError);
+#endif
+
+ // Tell SandboxTest that this process is done with all tests.
+ SendTestCompleted();
+}
+
+void SandboxTestingChild::ActorDestroy(ActorDestroyReason aWhy) {
+ MOZ_ASSERT(mThread->IsOnThread());
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "SandboxChildDestroyer", []() { SandboxTestingChild::Destroy(); }));
+}
+
+void SandboxTestingChild::Destroy() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(sInstance);
+ sInstance = nullptr;
+}
+
+ipc::IPCResult SandboxTestingChild::RecvShutDown() {
+ Close();
+ return IPC_OK();
+}
+
+void SandboxTestingChild::ReportNoTests() {
+ SendReportTestResults("dummy_test"_ns, /* passed */ true,
+ "The test framework fails if there are no cases."_ns);
+}
+
+template <typename F>
+void SandboxTestingChild::ErrnoTest(const nsCString& aName, bool aExpectSuccess,
+ F&& aFunction) {
+ int status = aFunction() >= 0 ? 0 : errno;
+ PosixTest(aName, aExpectSuccess, status);
+}
+
+template <typename F>
+void SandboxTestingChild::ErrnoValueTest(const nsCString& aName,
+ int aExpectedErrno, F&& aFunction) {
+ int status = aFunction() >= 0 ? 0 : errno;
+ PosixTest(aName, aExpectedErrno == 0, status, Some(aExpectedErrno));
+}
+
+void SandboxTestingChild::PosixTest(const nsCString& aName, bool aExpectSuccess,
+ int aStatus, Maybe<int> aExpectedError) {
+ nsAutoCString message;
+ bool passed;
+
+ // The "expected" arguments are a little redundant.
+ MOZ_ASSERT(!aExpectedError || aExpectSuccess == (*aExpectedError == 0));
+
+ // Decide whether the test passed, and stringify the actual result.
+ if (aStatus == 0) {
+ message = "Succeeded"_ns;
+ passed = aExpectSuccess;
+ } else {
+ message = "Error: "_ns;
+ message += strerror(aStatus);
+ if (aExpectedError) {
+ passed = aStatus == *aExpectedError;
+ } else {
+ passed = !aExpectSuccess;
+ }
+ }
+
+ // If something unexpected happened, mention the expected result.
+ if (!passed) {
+ message += "; expected ";
+ if (aExpectSuccess) {
+ message += "success";
+ } else {
+ message += "error";
+ if (aExpectedError) {
+ message += ": ";
+ message += strerror(*aExpectedError);
+ }
+ }
+ }
+
+ SendReportTestResults(aName, passed, message);
+}
+
+} // namespace mozilla