Commit 2f2588cf authored by Nika Layzell's avatar Nika Layzell
Browse files

Bug 1828389 - Ensure IPC channel is closed with error after KillHard, r=ipc-reviewers,mccr8

This patch changes KillHard() such that the IPC channel is immediately
shut down with an error after a KillHard() is performed. This is done by
fixing the previously-broken CLOSE_CHANNEL_WITH_ERROR support in
ShutDownProcess, and calling that method after KillHard().

This ensures that after the process has been killed, no further messages
will be delivered and processed, even if they were sent before the
process was killed.

In addition, the assertions and KillHard calls which are disabled for
fuzzing were changed to also shut down the channel, making fuzzing IPC
errors cause the connection to be terminated like it is in production
for these actors.

This change does not impact actors which ignore processing errors.

Differential Revision: https://phabricator.services.mozilla.com/D178383
parent 759d19c6
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -1879,18 +1879,19 @@ bool ContentParent::ShutDownProcess(ShutDownMethod aMethod) {
    qms->AbortOperationsForProcess(mChildID);
  }

  // If Close() fails with an error, we'll end up back in this function, but
  // with aMethod = CLOSE_CHANNEL_WITH_ERROR.

  if (aMethod == CLOSE_CHANNEL) {
  if (aMethod == CLOSE_CHANNEL || aMethod == CLOSE_CHANNEL_WITH_ERROR) {
    if (!mCalledClose) {
      MaybeLogBlockShutdownDiagnostics(
          this, "ShutDownProcess: Closing channel.", __FILE__, __LINE__);
      // Close() can only be called once: It kicks off the destruction
      // sequence.
      // Close()/CloseWithError() can only be called once: They kick off the
      // destruction sequence.
      mCalledClose = true;
      if (aMethod == CLOSE_CHANNEL_WITH_ERROR) {
        CloseWithError();
      } else {
        Close();
      }
    }
    result = true;
  }

@@ -2074,10 +2075,11 @@ void ContentParent::ProcessingError(Result aCode, const char* aReason) {
  if (MsgDropped == aCode) {
    return;
  }
#ifndef FUZZING
  // Other errors are big deals.
#ifndef FUZZING
  KillHard(aReason);
#endif
  ShutDownProcess(CLOSE_CHANNEL_WITH_ERROR);
}

void ContentParent::ActorDestroy(ActorDestroyReason why) {
@@ -4515,6 +4517,7 @@ void ContentParent::KillHard(const char* aReason) {
  ProcessHandle otherProcessHandle;
  if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle)) {
    NS_ERROR("Failed to open child process when attempting kill.");
    ShutDownProcess(CLOSE_CHANNEL_WITH_ERROR);
    return;
  }

@@ -4535,6 +4538,10 @@ void ContentParent::KillHard(const char* aReason) {
    mSubprocess->SetAlreadyDead();
  }

  // After we've killed the remote process, also ensure we close the IPC channel
  // with an error to immediately stop all IPC communication on this channel.
  ShutDownProcess(CLOSE_CHANNEL_WITH_ERROR);

  // EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
  XRE_GetIOMessageLoop()->PostTask(
      NewRunnableFunction("EnsureProcessTerminatedRunnable",
+1 −1
Original line number Diff line number Diff line
@@ -859,7 +859,7 @@ void RemoteDecoderManagerChild::DeallocateSurfaceDescriptor(
      })));
}

void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const {
void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) {
  dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
}

+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ class RemoteDecoderManagerChild final
      RemoteDecodeIn aLocation);

 protected:
  void HandleFatalError(const char* aMsg) const override;
  void HandleFatalError(const char* aMsg) override;

  PRemoteDecoderChild* AllocPRemoteDecoderChild(
      const RemoteDecoderInfoIPDL& aRemoteDecoderInfo,
+1 −1
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ void VsyncBridgeChild::ProcessingError(Result aCode, const char* aReason) {
                     "Processing error in VsyncBridgeChild");
}

void VsyncBridgeChild::HandleFatalError(const char* aMsg) const {
void VsyncBridgeChild::HandleFatalError(const char* aMsg) {
  dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
}

+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {

  void NotifyVsync(const VsyncEvent& aVsync, const layers::LayersId& aLayersId);

  void HandleFatalError(const char* aMsg) const override;
  void HandleFatalError(const char* aMsg) override;

 private:
  VsyncBridgeChild(RefPtr<VsyncIOThreadHolder>, const uint64_t& aProcessToken);
Loading