tor-browser

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

SocketProcessHost.cpp (8426B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "SocketProcessHost.h"
      7 
      8 #include "SocketProcessParent.h"
      9 #include "mozilla/dom/ContentParent.h"
     10 #include "mozilla/ipc/FileDescriptor.h"
     11 #include "mozilla/ipc/ProcessUtils.h"
     12 #include "nsAppRunner.h"
     13 #include "nsIOService.h"
     14 #include "nsIObserverService.h"
     15 #include "ProfilerParent.h"
     16 #include "nsNetUtil.h"
     17 #include "mozilla/ipc/Endpoint.h"
     18 #include "mozilla/ipc/ProcessChild.h"
     19 
     20 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
     21 #  include "mozilla/SandboxBroker.h"
     22 #  include "mozilla/SandboxBrokerPolicyFactory.h"
     23 #  include "mozilla/SandboxSettings.h"
     24 #endif
     25 
     26 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     27 #  include "mozilla/Sandbox.h"
     28 #endif
     29 
     30 #if defined(XP_WIN)
     31 #  include "mozilla/WinDllServices.h"
     32 #endif
     33 
     34 using namespace mozilla::ipc;
     35 
     36 namespace mozilla {
     37 namespace net {
     38 
     39 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     40 bool SocketProcessHost::sLaunchWithMacSandbox = false;
     41 #endif
     42 
     43 SocketProcessHost::SocketProcessHost(Listener* aListener)
     44    : GeckoChildProcessHost(GeckoProcessType_Socket),
     45      mListener(aListener),
     46      mTaskFactory(Some(this)),
     47      mLaunchPhase(LaunchPhase::Unlaunched),
     48      mShutdownRequested(false),
     49      mChannelClosed(false) {
     50  MOZ_ASSERT(NS_IsMainThread());
     51  MOZ_COUNT_CTOR(SocketProcessHost);
     52 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     53  if (!sLaunchWithMacSandbox) {
     54    sLaunchWithMacSandbox =
     55        (PR_GetEnv("MOZ_DISABLE_SOCKET_PROCESS_SANDBOX") == nullptr);
     56  }
     57  mDisableOSActivityMode = sLaunchWithMacSandbox;
     58 #endif
     59 }
     60 
     61 SocketProcessHost::~SocketProcessHost() { MOZ_COUNT_DTOR(SocketProcessHost); }
     62 
     63 bool SocketProcessHost::Launch() {
     64  MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
     65  MOZ_ASSERT(!mSocketProcessParent);
     66  MOZ_ASSERT(NS_IsMainThread());
     67 
     68  geckoargs::ChildProcessArgs extraArgs;
     69  ProcessChild::AddPlatformBuildID(extraArgs);
     70 
     71  SharedPreferenceSerializer prefSerializer;
     72  if (!prefSerializer.SerializeToSharedMemory(GeckoProcessType_VR,
     73                                              /* remoteType */ ""_ns)) {
     74    return false;
     75  }
     76  prefSerializer.AddSharedPrefCmdLineArgs(*this, extraArgs);
     77 
     78  mLaunchPhase = LaunchPhase::Waiting;
     79  if (!GeckoChildProcessHost::LaunchAndWaitForProcessHandle(
     80          std::move(extraArgs))) {
     81    mLaunchPhase = LaunchPhase::Complete;
     82    return false;
     83  }
     84 
     85  return true;
     86 }
     87 
     88 static void HandleErrorAfterDestroy(
     89    RefPtr<SocketProcessHost::Listener>&& aListener) {
     90  if (!aListener) {
     91    return;
     92  }
     93 
     94  NS_DispatchToMainThread(NS_NewRunnableFunction(
     95      "HandleErrorAfterDestroy", [listener = std::move(aListener)]() {
     96        listener->OnProcessLaunchComplete(nullptr, false);
     97      }));
     98 }
     99 
    100 void SocketProcessHost::OnChannelConnected(base::ProcessId peer_pid) {
    101  MOZ_ASSERT(!NS_IsMainThread());
    102 
    103  GeckoChildProcessHost::OnChannelConnected(peer_pid);
    104 
    105  // Post a task to the main thread. Take the lock because mTaskFactory is not
    106  // thread-safe.
    107  RefPtr<Runnable> runnable;
    108  {
    109    MonitorAutoLock lock(mMonitor);
    110    if (!mTaskFactory) {
    111      HandleErrorAfterDestroy(std::move(mListener));
    112      return;
    113    }
    114    runnable =
    115        (*mTaskFactory)
    116            .NewRunnableMethod(&SocketProcessHost::OnChannelConnectedTask);
    117  }
    118  NS_DispatchToMainThread(runnable);
    119 }
    120 
    121 void SocketProcessHost::OnChannelConnectedTask() {
    122  MOZ_ASSERT(NS_IsMainThread());
    123 
    124  if (mLaunchPhase == LaunchPhase::Waiting) {
    125    InitAfterConnect(true);
    126  }
    127 }
    128 
    129 void SocketProcessHost::InitAfterConnect(bool aSucceeded) {
    130  MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
    131  MOZ_ASSERT(!mSocketProcessParent);
    132  MOZ_ASSERT(NS_IsMainThread());
    133 
    134  mLaunchPhase = LaunchPhase::Complete;
    135  if (!aSucceeded) {
    136    if (mListener) {
    137      mListener->OnProcessLaunchComplete(this, false);
    138    }
    139    return;
    140  }
    141 
    142  mSocketProcessParent = MakeRefPtr<SocketProcessParent>(this);
    143  DebugOnly<bool> rv = TakeInitialEndpoint().Bind(mSocketProcessParent.get());
    144  MOZ_ASSERT(rv);
    145 
    146  SocketPorcessInitAttributes attributes;
    147  nsCOMPtr<nsIIOService> ioService(do_GetIOService());
    148  MOZ_ASSERT(ioService, "No IO service?");
    149  DebugOnly<nsresult> result = ioService->GetOffline(&attributes.mOffline());
    150  MOZ_ASSERT(NS_SUCCEEDED(result), "Failed getting offline?");
    151  result = ioService->GetConnectivity(&attributes.mConnectivity());
    152  MOZ_ASSERT(NS_SUCCEEDED(result), "Failed getting connectivity?");
    153 
    154  attributes.mInitSandbox() = false;
    155 
    156 #if defined(XP_WIN)
    157  RefPtr<DllServices> dllSvc(DllServices::Get());
    158  attributes.mIsReadyForBackgroundProcessing() =
    159      dllSvc->IsReadyForBackgroundProcessing();
    160 #endif
    161 
    162 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
    163  if (GetEffectiveSocketProcessSandboxLevel() > 0) {
    164    auto policy = SandboxBrokerPolicyFactory::GetSocketProcessPolicy(
    165        GetActor()->OtherPid());
    166    if (policy != nullptr) {
    167      attributes.mSandboxBroker() = Some(FileDescriptor());
    168      mSandboxBroker =
    169          SandboxBroker::Create(std::move(policy), GetActor()->OtherPid(),
    170                                attributes.mSandboxBroker().ref());
    171      // This is unlikely to fail and probably indicates OS resource
    172      // exhaustion.
    173      (void)NS_WARN_IF(mSandboxBroker == nullptr);
    174      MOZ_ASSERT(attributes.mSandboxBroker().ref().IsValid());
    175    }
    176    attributes.mInitSandbox() = true;
    177  }
    178 #endif  // XP_LINUX && MOZ_SANDBOX
    179 
    180  (void)GetActor()->SendInit(attributes);
    181 
    182  (void)GetActor()->SendInitProfiler(
    183      ProfilerParent::CreateForProcess(GetActor()->OtherPid()));
    184 
    185  if (mListener) {
    186    mListener->OnProcessLaunchComplete(this, true);
    187  }
    188 }
    189 
    190 void SocketProcessHost::Shutdown() {
    191  MOZ_ASSERT(!mShutdownRequested);
    192  MOZ_ASSERT(NS_IsMainThread());
    193 
    194  mListener = nullptr;
    195 
    196  if (mSocketProcessParent) {
    197    // OnChannelClosed uses this to check if the shutdown was expected or
    198    // unexpected.
    199    mShutdownRequested = true;
    200 
    201    // The channel might already be closed if we got here unexpectedly.
    202    if (!mChannelClosed) {
    203      mSocketProcessParent->Close();
    204    }
    205 
    206    return;
    207  }
    208 
    209  DestroyProcess();
    210 }
    211 
    212 void SocketProcessHost::OnChannelClosed() {
    213  MOZ_ASSERT(NS_IsMainThread());
    214 
    215  mChannelClosed = true;
    216 
    217  if (!mShutdownRequested && mListener) {
    218    // This is an unclean shutdown. Notify our listener that we're going away.
    219    mListener->OnProcessUnexpectedShutdown(this);
    220  } else {
    221    DestroyProcess();
    222  }
    223 
    224  // Release the actor.
    225  SocketProcessParent::Destroy(std::move(mSocketProcessParent));
    226  MOZ_ASSERT(!mSocketProcessParent);
    227 }
    228 
    229 void SocketProcessHost::DestroyProcess() {
    230  {
    231    MonitorAutoLock lock(mMonitor);
    232    mTaskFactory.reset();
    233  }
    234 
    235  GetCurrentSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
    236      "DestroySocketProcessRunnable", [this] { Destroy(); }));
    237 }
    238 
    239 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
    240 bool SocketProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
    241  GeckoChildProcessHost::FillMacSandboxInfo(aInfo);
    242  if (!aInfo.shouldLog && PR_GetEnv("MOZ_SANDBOX_SOCKET_PROCESS_LOGGING")) {
    243    aInfo.shouldLog = true;
    244  }
    245  return true;
    246 }
    247 
    248 /* static */
    249 MacSandboxType SocketProcessHost::GetMacSandboxType() {
    250  return MacSandboxType_Socket;
    251 }
    252 #endif
    253 
    254 //-----------------------------------------------------------------------------
    255 // SocketProcessMemoryReporter
    256 //-----------------------------------------------------------------------------
    257 
    258 bool SocketProcessMemoryReporter::IsAlive() const {
    259  MOZ_ASSERT(gIOService);
    260 
    261  if (!gIOService->mSocketProcess) {
    262    return false;
    263  }
    264 
    265  return gIOService->mSocketProcess->IsConnected();
    266 }
    267 
    268 bool SocketProcessMemoryReporter::SendRequestMemoryReport(
    269    const uint32_t& aGeneration, const bool& aAnonymize,
    270    const bool& aMinimizeMemoryUsage,
    271    const Maybe<ipc::FileDescriptor>& aDMDFile) {
    272  MOZ_ASSERT(gIOService);
    273 
    274  if (!gIOService->mSocketProcess) {
    275    return false;
    276  }
    277 
    278  SocketProcessParent* actor = gIOService->mSocketProcess->GetActor();
    279  if (!actor) {
    280    return false;
    281  }
    282 
    283  return actor->SendRequestMemoryReport(aGeneration, aAnonymize,
    284                                        aMinimizeMemoryUsage, aDMDFile);
    285 }
    286 
    287 int32_t SocketProcessMemoryReporter::Pid() const {
    288  MOZ_ASSERT(gIOService);
    289  return gIOService->SocketProcessPid();
    290 }
    291 
    292 }  // namespace net
    293 }  // namespace mozilla