Bug 1584721 - P1. Add ability to create unsafe shmem with ShmemPool. r=mjf
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 01 Oct 2019 11:23:22 +0000
changeset 495737 ae74c8a033d0e52ddf1ce6d9e2122347c52e1c4b
parent 495736 577cd174fedbc68daa18f9ab144b9e023f8dd3d9
child 495738 b4de320b347971aa9a0e3b7ba3519c72b656b6f8
push id96833
push userjyavenard@mozilla.com
push dateTue, 01 Oct 2019 16:30:16 +0000
treeherderautoland@3f6d096c5358 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmjf
bugs1584721
milestone71.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 1584721 - P1. Add ability to create unsafe shmem with ShmemPool. r=mjf By default, the remote process takes ownership of a shmem when it's sent over ipc. Using "unsafe" shmem allows any processes to read/write/deallocate such shmem. Differential Revision: https://phabricator.services.mozilla.com/D47554
dom/media/systemservices/ShmemPool.h
--- a/dom/media/systemservices/ShmemPool.h
+++ b/dom/media/systemservices/ShmemPool.h
@@ -2,18 +2,18 @@
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* 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 http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ShmemPool_h
 #define mozilla_ShmemPool_h
 
+#include "mozilla/Mutex.h"
 #include "mozilla/ipc/Shmem.h"
-#include "mozilla/Mutex.h"
 
 extern mozilla::LazyLogModule sShmemPoolLog;
 #define SHMEMPOOL_LOG(args) \
   MOZ_LOG(sShmemPoolLog, mozilla::LogLevel::Debug, args)
 #define SHMEMPOOL_LOG_WARN(args) \
   MOZ_LOG(sShmemPoolLog, mozilla::LogLevel::Warning, args)
 #define SHMEMPOOL_LOG_ERROR(args) \
   MOZ_LOG(sShmemPoolLog, mozilla::LogLevel::Error, args)
@@ -76,18 +76,21 @@ class ShmemPool {
     for (size_t i = 0; i < mShmemPool.Length(); i++) {
       if (mShmemPool[i].mInitialized) {
         aInstance->DeallocShmem(mShmemPool[i].Get());
         mShmemPool[i].mInitialized = false;
       }
     }
   }
 
+  enum class AllocationPolicy { Default, Unsafe };
+
   template <class T>
-  ShmemBuffer Get(T* aInstance, size_t aSize) {
+  ShmemBuffer Get(T* aInstance, size_t aSize,
+                  AllocationPolicy aPolicy = AllocationPolicy::Default) {
     MutexAutoLock lock(mMutex);
 
     // Pool is empty, don't block caller.
     if (mPoolFree == 0) {
       if (!mErrorLogged) {
         // log "out of pool" once as error to avoid log spam
         mErrorLogged = true;
         SHMEMPOOL_LOG_ERROR(
@@ -99,35 +102,34 @@ class ShmemPool {
       // This isn't initialized, so will be understood as an error.
       return ShmemBuffer();
     }
 
     ShmemBuffer& res = mShmemPool[mPoolFree - 1];
 
     if (!res.mInitialized) {
       SHMEMPOOL_LOG(("Initializing new Shmem in pool"));
-      if (!aInstance->AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC,
-                                 &res.mShmem)) {
+      if (!AllocateShmem(aInstance, aSize, res, aPolicy)) {
         SHMEMPOOL_LOG(("Failure allocating new Shmem buffer"));
         return ShmemBuffer();
       }
       res.mInitialized = true;
     }
 
-    MOZ_ASSERT(res.mShmem.IsWritable(), "Shmem in Pool is not writable?");
+    MOZ_DIAGNOSTIC_ASSERT(res.mShmem.IsWritable(),
+                          "Shmem in Pool is not writable?");
 
     // Prepare buffer, increase size if needed (we never shrink as we don't
     // maintain seperate sized pools and we don't want to keep reallocating)
     if (res.mShmem.Size<char>() < aSize) {
       SHMEMPOOL_LOG(("Size change/increase in Shmem Pool"));
       aInstance->DeallocShmem(res.mShmem);
       res.mInitialized = false;
       // this may fail; always check return value
-      if (!aInstance->AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC,
-                                 &res.mShmem)) {
+      if (!AllocateShmem(aInstance, aSize, res, aPolicy)) {
         SHMEMPOOL_LOG(("Failure allocating resized Shmem buffer"));
         return ShmemBuffer();
       } else {
         res.mInitialized = true;
       }
     }
 
     MOZ_ASSERT(res.mShmem.IsWritable(),
@@ -141,16 +143,26 @@ class ShmemPool {
       SHMEMPOOL_LOG(
           ("Maximum ShmemPool use increased: %zu buffers", mMaxPoolUse));
     }
 #endif
     return std::move(res);
   }
 
  private:
+  template <class T>
+  bool AllocateShmem(T* aInstance, size_t aSize, ShmemBuffer& aRes,
+                     AllocationPolicy aPolicy) {
+    return (aPolicy == AllocationPolicy::Default &&
+            aInstance->AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC,
+                                  &aRes.mShmem)) ||
+           (aPolicy == AllocationPolicy::Unsafe &&
+            aInstance->AllocUnsafeShmem(aSize, ipc::SharedMemory::TYPE_BASIC,
+                                        &aRes.mShmem));
+  }
   Mutex mMutex;
   size_t mPoolFree;
   bool mErrorLogged;
 #ifdef DEBUG
   size_t mMaxPoolUse;
 #endif
   nsTArray<ShmemBuffer> mShmemPool;
 };