tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SandboxTestingChild.cpp (5609B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SandboxTestingChild.h"
      8 #include "SandboxTestingChildTests.h"
      9 #include "SandboxTestingThread.h"
     10 #include "mozilla/ipc/Endpoint.h"
     11 #include "mozilla/ipc/UtilityProcessSandboxing.h"
     12 #include "mozilla/ipc/UtilityProcessChild.h"
     13 
     14 #ifdef XP_LINUX
     15 #  include "mozilla/Sandbox.h"
     16 #endif
     17 
     18 #include "nsXULAppAPI.h"
     19 
     20 namespace mozilla {
     21 
     22 StaticRefPtr<SandboxTestingChild> SandboxTestingChild::sInstance;
     23 
     24 bool SandboxTestingChild::IsTestThread() { return mThread->IsOnThread(); }
     25 
     26 void SandboxTestingChild::PostToTestThread(
     27    already_AddRefed<nsIRunnable>&& runnable) {
     28  mThread->Dispatch(std::move(runnable));
     29 }
     30 
     31 /* static */
     32 bool SandboxTestingChild::Initialize(
     33    Endpoint<PSandboxTestingChild>&& aSandboxTestingEndpoint) {
     34  MOZ_ASSERT(!sInstance);
     35  SandboxTestingThread* thread = SandboxTestingThread::Create();
     36  if (!thread) {
     37    return false;
     38  }
     39  sInstance =
     40      new SandboxTestingChild(thread, std::move(aSandboxTestingEndpoint));
     41  thread->Dispatch(NewRunnableMethod<Endpoint<PSandboxTestingChild>&&>(
     42      "SandboxTestingChild::Bind", sInstance.get(), &SandboxTestingChild::Bind,
     43      std::move(aSandboxTestingEndpoint)));
     44  return true;
     45 }
     46 
     47 /* static */
     48 SandboxTestingChild* SandboxTestingChild::GetInstance() {
     49  MOZ_ASSERT(sInstance, "Must initialize SandboxTestingChild before using it");
     50  return sInstance;
     51 }
     52 
     53 SandboxTestingChild::SandboxTestingChild(
     54    SandboxTestingThread* aThread, Endpoint<PSandboxTestingChild>&& aEndpoint)
     55    : mThread(aThread) {}
     56 
     57 SandboxTestingChild::~SandboxTestingChild() = default;
     58 
     59 void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
     60  MOZ_RELEASE_ASSERT(mThread->IsOnThread());
     61  DebugOnly<bool> ok = aEndpoint.Bind(this);
     62  MOZ_ASSERT(ok);
     63 
     64 #ifdef XP_LINUX
     65  bool sandboxCrashOnError = SetSandboxCrashOnError(false);
     66 #endif
     67 
     68  if (XRE_IsContentProcess()) {
     69    RunTestsContent(this);
     70  }
     71 
     72  if (XRE_IsRDDProcess()) {
     73    RunTestsRDD(this);
     74  }
     75 
     76  if (XRE_IsGMPluginProcess()) {
     77    RunTestsGMPlugin(this);
     78  }
     79 
     80  if (XRE_IsSocketProcess()) {
     81    RunTestsSocket(this);
     82  }
     83 
     84  if (XRE_IsGPUProcess()) {
     85    RunTestsGPU(this);
     86  }
     87 
     88  if (XRE_IsUtilityProcess()) {
     89    RefPtr<ipc::UtilityProcessChild> s = ipc::UtilityProcessChild::Get();
     90    MOZ_ASSERT(s, "Unable to grab a UtilityProcessChild");
     91    switch (s->mSandbox) {
     92      case ipc::SandboxingKind::GENERIC_UTILITY:
     93        RunTestsGenericUtility(this);
     94        RunTestsUtilityMediaService(this, s->mSandbox);
     95        break;
     96 #ifdef MOZ_APPLEMEDIA
     97      case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA:
     98        RunTestsUtilityMediaService(this, s->mSandbox);
     99        break;
    100 #endif
    101 #ifdef XP_WIN
    102      case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
    103        RunTestsUtilityMediaService(this, s->mSandbox);
    104        break;
    105 #endif
    106 
    107      default:
    108        MOZ_ASSERT(false, "Invalid SandboxingKind");
    109        break;
    110    }
    111  }
    112 
    113 #ifdef XP_LINUX
    114  SetSandboxCrashOnError(sandboxCrashOnError);
    115 #endif
    116 
    117  // Tell SandboxTest that this process is done with all tests.
    118  SendTestCompleted();
    119 }
    120 
    121 void SandboxTestingChild::ActorDestroy(ActorDestroyReason aWhy) {
    122  MOZ_ASSERT(mThread->IsOnThread());
    123  NS_DispatchToMainThread(NS_NewRunnableFunction(
    124      "SandboxChildDestroyer", []() { SandboxTestingChild::Destroy(); }));
    125 }
    126 
    127 void SandboxTestingChild::Destroy() {
    128  MOZ_ASSERT(NS_IsMainThread());
    129  MOZ_ASSERT(sInstance);
    130  sInstance = nullptr;
    131 }
    132 
    133 ipc::IPCResult SandboxTestingChild::RecvShutDown() {
    134  Close();
    135  return IPC_OK();
    136 }
    137 
    138 void SandboxTestingChild::ReportNoTests() {
    139  SendReportTestResults("dummy_test"_ns, /* passed */ true,
    140                        "The test framework fails if there are no cases."_ns);
    141 }
    142 
    143 template <typename F>
    144 void SandboxTestingChild::ErrnoTest(const nsCString& aName, bool aExpectSuccess,
    145                                    F&& aFunction) {
    146  int status = aFunction() >= 0 ? 0 : errno;
    147  PosixTest(aName, aExpectSuccess, status);
    148 }
    149 
    150 template <typename F>
    151 void SandboxTestingChild::ErrnoValueTest(const nsCString& aName,
    152                                         int aExpectedErrno, F&& aFunction) {
    153  int status = aFunction() >= 0 ? 0 : errno;
    154  PosixTest(aName, aExpectedErrno == 0, status, Some(aExpectedErrno));
    155 }
    156 
    157 void SandboxTestingChild::PosixTest(const nsCString& aName, bool aExpectSuccess,
    158                                    int aStatus, Maybe<int> aExpectedError) {
    159  nsAutoCString message;
    160  bool passed;
    161 
    162  // The "expected" arguments are a little redundant.
    163  MOZ_ASSERT(!aExpectedError || aExpectSuccess == (*aExpectedError == 0));
    164 
    165  // Decide whether the test passed, and stringify the actual result.
    166  if (aStatus == 0) {
    167    message = "Succeeded"_ns;
    168    passed = aExpectSuccess;
    169  } else {
    170    message = "Error: "_ns;
    171    message += strerror(aStatus);
    172    if (aExpectedError) {
    173      passed = aStatus == *aExpectedError;
    174    } else {
    175      passed = !aExpectSuccess;
    176    }
    177  }
    178 
    179  // If something unexpected happened, mention the expected result.
    180  if (!passed) {
    181    message += "; expected ";
    182    if (aExpectSuccess) {
    183      message += "success";
    184    } else {
    185      message += "error";
    186      if (aExpectedError) {
    187        message += ": ";
    188        message += strerror(*aExpectedError);
    189      }
    190    }
    191  }
    192 
    193  SendReportTestResults(aName, passed, message);
    194 }
    195 
    196 }  // namespace mozilla