Bug 1466877 Part 4 - Graphics shmem changes for sandboxing, r=jld.
authorBrian Hackett <bhackett1024@gmail.com>
Sun, 22 Jul 2018 11:56:17 +0000
changeset 427738 dc52c82903fcb7978a887893fd83d92363cd6d9d
parent 427737 e331895810fba7f631b1c67abe8e861c783a4abc
child 427739 2500fc654564002eea1ba8f974e6f560a55e7835
push id34314
push usercsabou@mozilla.com
push dateMon, 23 Jul 2018 09:31:12 +0000
treeherdermozilla-central@143984185dce [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjld
bugs1466877
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1466877 Part 4 - Graphics shmem changes for sandboxing, r=jld.
toolkit/recordreplay/ipc/Channel.h
toolkit/recordreplay/ipc/ChildIPC.cpp
toolkit/recordreplay/ipc/ChildProcess.cpp
toolkit/recordreplay/ipc/ParentGraphics.cpp
toolkit/recordreplay/ipc/ParentInternal.h
--- a/toolkit/recordreplay/ipc/Channel.h
+++ b/toolkit/recordreplay/ipc/Channel.h
@@ -453,19 +453,12 @@ public:
 };
 
 // Command line option used to specify the middleman pid for a child process.
 static const char* gMiddlemanPidOption = "-middlemanPid";
 
 // Command line option used to specify the channel ID for a child process.
 static const char* gChannelIDOption = "-recordReplayChannelID";
 
-// ID for the mach message sent when notifying a subprocess about the graphics
-// shared memory buffer.
-static const int32_t GraphicsMessageId = 42;
-
-// Fixed size of the graphics shared memory buffer.
-static const size_t GraphicsMemorySize = 4096 * 4096 * 4;
-
 } // namespace recordreplay
 } // namespace mozilla
 
 #endif // mozilla_recordreplay_Channel_h
--- a/toolkit/recordreplay/ipc/ChildIPC.cpp
+++ b/toolkit/recordreplay/ipc/ChildIPC.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/VsyncDispatcher.h"
 
 #include "InfallibleVector.h"
 #include "MemorySnapshot.h"
 #include "Monitor.h"
+#include "ParentInternal.h"
 #include "ProcessRecordReplay.h"
 #include "ProcessRedirect.h"
 #include "ProcessRewind.h"
 #include "Thread.h"
 #include "Units.h"
 
 #include <algorithm>
 #include <mach/mach_vm.h>
@@ -221,47 +222,48 @@ InitRecordingOrReplayingProcess(int* aAr
 
   Thread::StartThread(ListenForCheckpointThreadMain, nullptr, false);
 
   InitDebuggerHooks();
 
   pt.emplace();
 
   // Setup a mach port to receive the graphics shmem handle over.
-  char portName[128];
-  SprintfLiteral(portName, "WebReplay.%d.%d", gMiddlemanPid, channelID.ref());
-  ReceivePort receivePort(portName);
+  ReceivePort receivePort(nsPrintfCString("WebReplay.%d.%d", gMiddlemanPid, (int) channelID.ref()).get());
 
-  pt.reset();
+  MachSendMessage handshakeMessage(parent::GraphicsHandshakeMessageId);
+  handshakeMessage.AddDescriptor(MachMsgPortDescriptor(receivePort.GetPort(), MACH_MSG_TYPE_COPY_SEND));
 
-  // We are ready to receive initialization messages from the middleman, pause
-  // so they can be sent.
-  HitCheckpoint(InvalidCheckpointId, /* aRecordingEndpoint = */ false);
-
-  pt.emplace();
+  MachPortSender sender(nsPrintfCString("WebReplay.%d", gMiddlemanPid).get());
+  kern_return_t kr = sender.SendMessage(handshakeMessage, 1000);
+  MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
 
-  // The parent should have sent us a handle to the graphics shmem.
+  // The parent should send us a handle to the graphics shmem.
   MachReceiveMessage message;
-  kern_return_t kr = receivePort.WaitForMessage(&message, 0);
+  kr = receivePort.WaitForMessage(&message, 0);
   MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
-  MOZ_RELEASE_ASSERT(message.GetMessageID() == GraphicsMessageId);
+  MOZ_RELEASE_ASSERT(message.GetMessageID() == parent::GraphicsMemoryMessageId);
   mach_port_t graphicsPort = message.GetTranslatedPort(0);
   MOZ_RELEASE_ASSERT(graphicsPort != MACH_PORT_NULL);
 
   mach_vm_address_t address = 0;
-  kr = mach_vm_map(mach_task_self(), &address, GraphicsMemorySize, 0, VM_FLAGS_ANYWHERE,
+  kr = mach_vm_map(mach_task_self(), &address, parent::GraphicsMemorySize, 0, VM_FLAGS_ANYWHERE,
                    graphicsPort, 0, false,
                    VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE,
                    VM_INHERIT_NONE);
   MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
 
   gGraphicsShmem = (void*) address;
 
   pt.reset();
 
+  // We are ready to receive initialization messages from the middleman, pause
+  // so they can be sent.
+  HitCheckpoint(CheckpointId::Invalid, /* aRecordingEndpoint = */ false);
+
   // Process the introduction message to fill in arguments.
   MOZ_RELEASE_ASSERT(!gShmemPrefs);
   MOZ_RELEASE_ASSERT(gParentArgv.empty());
 
   gParentPid = gIntroductionMessage->mParentPid;
 
   // Record/replay the introduction message itself so we get consistent args
   // and prefs between recording and replaying.
@@ -387,17 +389,17 @@ EndIdleTime()
 
 static void
 HitCheckpoint(size_t aId, bool aRecordingEndpoint)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   double time = CurrentTime();
   PauseMainThreadAndInvokeCallback([=]() {
       double duration = 0;
-      if (aId > FirstCheckpointId) {
+      if (aId > CheckpointId::First) {
         duration = time - gLastCheckpointTime;
         MOZ_RELEASE_ASSERT(duration > 0);
       }
       gChannel->SendMessage(HitCheckpointMessage(aId, aRecordingEndpoint, duration));
     });
   gLastCheckpointTime = time;
 }
 
--- a/toolkit/recordreplay/ipc/ChildProcess.cpp
+++ b/toolkit/recordreplay/ipc/ChildProcess.cpp
@@ -470,28 +470,21 @@ ChildProcessInfo::LaunchSubprocess()
       MOZ_CRASH("ChildProcessInfo::LaunchSubprocess");
     }
   } else {
     dom::ContentChild::GetSingleton()->SendCreateReplayingProcess(channelId);
   }
 
   mLastMessageTime = TimeStamp::Now();
 
+  SendGraphicsMemoryToChild();
+
   // The child should send us a HitCheckpoint with an invalid ID to pause.
   WaitUntilPaused();
 
-  // Send the child a handle to the graphics shmem via mach IPC.
-  char portName[128];
-  SprintfLiteral(portName, "WebReplay.%d.%d", getpid(), (int) channelId);
-  MachPortSender sender(portName);
-  MachSendMessage message(GraphicsMessageId);
-  message.AddDescriptor(MachMsgPortDescriptor(gGraphicsPort, MACH_MSG_TYPE_COPY_SEND));
-  kern_return_t kr = sender.SendMessage(message, 1000);
-  MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
-
   MOZ_RELEASE_ASSERT(gIntroductionMessage);
   SendMessage(*gIntroductionMessage);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Recovering Crashed / Hung Children
 ///////////////////////////////////////////////////////////////////////////////
 
--- a/toolkit/recordreplay/ipc/ParentGraphics.cpp
+++ b/toolkit/recordreplay/ipc/ParentGraphics.cpp
@@ -18,17 +18,19 @@
 
 #include <mach/mach_vm.h>
 
 namespace mozilla {
 namespace recordreplay {
 namespace parent {
 
 void* gGraphicsMemory;
-mach_port_t gGraphicsPort;
+
+static mach_port_t gGraphicsPort;
+static ReceivePort* gGraphicsReceiver;
 
 void
 InitializeGraphicsMemory()
 {
   mach_vm_address_t address;
   kern_return_t kr = mach_vm_allocate(mach_task_self(), &address,
                                       GraphicsMemorySize, VM_FLAGS_ANYWHERE);
   MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
@@ -39,13 +41,33 @@ InitializeGraphicsMemory()
                                  address,
                                  VM_PROT_DEFAULT,
                                  &gGraphicsPort,
                                  MACH_PORT_NULL);
   MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
   MOZ_RELEASE_ASSERT(memoryObjectSize == GraphicsMemorySize);
 
   gGraphicsMemory = (void*) address;
+  gGraphicsReceiver = new ReceivePort(nsPrintfCString("WebReplay.%d", getpid()).get());
+}
+
+void
+SendGraphicsMemoryToChild()
+{
+  MachReceiveMessage handshakeMessage;
+  kern_return_t kr = gGraphicsReceiver->WaitForMessage(&handshakeMessage, 0);
+  MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
+
+  MOZ_RELEASE_ASSERT(handshakeMessage.GetMessageID() == GraphicsHandshakeMessageId);
+  mach_port_t childPort = handshakeMessage.GetTranslatedPort(0);
+  MOZ_RELEASE_ASSERT(childPort != MACH_PORT_NULL);
+
+  MachSendMessage message(GraphicsMemoryMessageId);
+  message.AddDescriptor(MachMsgPortDescriptor(gGraphicsPort, MACH_MSG_TYPE_COPY_SEND));
+
+  MachPortSender sender(childPort);
+  kr = sender.SendMessage(message, 1000);
+  MOZ_RELEASE_ASSERT(kr == KERN_SUCCESS);
 }
 
 } // namespace parent
 } // namespace recordreplay
 } // namespace mozilla
--- a/toolkit/recordreplay/ipc/ParentInternal.h
+++ b/toolkit/recordreplay/ipc/ParentInternal.h
@@ -50,25 +50,36 @@ void Shutdown();
 
 // Monitor used for synchronizing between the main and channel or message loop threads.
 static Monitor* gMonitor;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Graphics
 ///////////////////////////////////////////////////////////////////////////////
 
-extern mach_port_t gGraphicsPort;
 extern void* gGraphicsMemory;
 
 void InitializeGraphicsMemory();
+void SendGraphicsMemoryToChild();
 
 // Update the graphics painted in the UI process, per painting data received
 // from a child process, or null for the last paint performed.
 void UpdateGraphicsInUIProcess(const PaintMessage* aMsg);
 
+// ID for the mach message sent from a child process to the middleman to
+// request a port for the graphics shmem.
+static const int32_t GraphicsHandshakeMessageId = 42;
+
+// ID for the mach message sent from the middleman to a child process with the
+// requested memory for.
+static const int32_t GraphicsMemoryMessageId = 43;
+
+// Fixed size of the graphics shared memory buffer.
+static const size_t GraphicsMemorySize = 4096 * 4096 * 4;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Child Processes
 ///////////////////////////////////////////////////////////////////////////////
 
 // Information about the role which a child process is fulfilling, and governs
 // how the process responds to incoming messages.
 class ChildRole
 {