Bug 1436566 - [Mac] Land disabled-by-default sandboxing for the Flash NPAPI plugin process. r=Alex_Gaynor r=jimm draft
authorHaik Aftandilian <haftandilian@mozilla.com>
Mon, 12 Feb 2018 15:46:31 -0800
changeset 754628 1b8126e47654dd613242e1581e35fcf48deb0e7c
parent 754627 efd5016495c8e9b8d568f85e34fb8419dfa3b5bf
push id98952
push userhaftandilian@mozilla.com
push dateTue, 13 Feb 2018 22:50:56 +0000
reviewersAlex_Gaynor, jimm
bugs1436566
milestone60.0a1
Bug 1436566 - [Mac] Land disabled-by-default sandboxing for the Flash NPAPI plugin process. r=Alex_Gaynor r=jimm MozReview-Commit-ID: Es0GbMLKvH5
browser/app/profile/firefox.js
dom/plugins/base/nsPluginTags.cpp
dom/plugins/base/nsPluginTags.h
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleChild.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginProcessChild.cpp
dom/plugins/ipc/PluginProcessParent.cpp
dom/plugins/ipc/PluginProcessParent.h
security/sandbox/mac/Sandbox.h
security/sandbox/mac/Sandbox.mm
security/sandbox/mac/SandboxPolicies.h
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1081,16 +1081,20 @@ pref("security.sandbox.gpu.level", 0);
 // 3 -> "no global read/write access, read access permitted to
 //       $PROFILE/{extensions,chrome}"
 // This setting is read when the content process is started. On Mac the content
 // process is killed when all windows are closed, so a change will take effect
 // when the 1st window is opened.
 pref("security.sandbox.content.level", 3);
 #endif
 
+#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+pref("security.sandbox.mac.flash.enabled", false);
+#endif
+
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
 // This pref is introduced as part of bug 742434, the naming is inspired from
 // its Windows/Mac counterpart, but on Linux it's an integer which means:
 // 0 -> "no sandbox"
 // 1 -> "content sandbox using seccomp-bpf when available"
 // 2 -> "seccomp-bpf + write file broker"
 // 3 -> "seccomp-bpf + read/write file brokering"
 // 4 -> all of the above + network/socket restrictions
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -230,16 +230,17 @@ nsPluginTag::nsPluginTag(nsPluginInfo* a
     mContentProcessRunningCount(0),
     mHadLocalInstance(false),
     mLibrary(nullptr),
     mIsFlashPlugin(false),
     mSupportsAsyncRender(false),
     mFullPath(aPluginInfo->fFullPath),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(0),
+    mIsSandboxLoggingEnabled(false),
     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
     mCachedBlocklistStateValid(false),
     mIsFromExtension(fromExtension)
 {
   InitMime(aPluginInfo->fMimeTypeArray,
            aPluginInfo->fMimeDescriptionArray,
            aPluginInfo->fExtensionArray,
            aPluginInfo->fVariantCount);
@@ -265,16 +266,17 @@ nsPluginTag::nsPluginTag(const char* aNa
     mContentProcessRunningCount(0),
     mHadLocalInstance(false),
     mLibrary(nullptr),
     mIsFlashPlugin(false),
     mSupportsAsyncRender(false),
     mFullPath(aFullPath),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(0),
+    mIsSandboxLoggingEnabled(false),
     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
     mCachedBlocklistStateValid(false),
     mIsFromExtension(fromExtension)
 {
   InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
            static_cast<uint32_t>(aVariants));
   InitSandboxLevel();
   if (!aArgsAreUTF8)
@@ -301,16 +303,17 @@ nsPluginTag::nsPluginTag(uint32_t aId,
                          aMimeDescriptions, aExtensions),
     mId(aId),
     mContentProcessRunningCount(0),
     mLibrary(nullptr),
     mIsFlashPlugin(aIsFlashPlugin),
     mSupportsAsyncRender(aSupportsAsyncRender),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(aSandboxLevel),
+    mIsSandboxLoggingEnabled(false),
     mNiceFileName(),
     mCachedBlocklistState(aBlocklistState),
     mCachedBlocklistStateValid(true),
     mIsFromExtension(aFromExtension)
 {
 }
 
 nsPluginTag::~nsPluginTag()
@@ -416,16 +419,40 @@ nsPluginTag::InitSandboxLevel()
   // As level 2 is now the default NPAPI sandbox level for 64-bit flash, we
   // don't want to allow a lower setting. This should be changed if the
   // firefox.js pref file is changed.
   if (mIsFlashPlugin && mSandboxLevel < 2) {
     mSandboxLevel = 2;
   }
 #endif
 #endif
+
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+  // At present, the Mac Flash NPAPI plugin sandbox is controlled via
+  // a boolean with no support for different levels. When the sandbox
+  // is enabled, we set the level to 1.
+  if (mIsFlashPlugin) {
+    // Allow enabling the sandbox via the pref
+    // security.sandbox.mac.flash.enabled or via the environment variable
+    // MOZ_SANDBOX_MAC_FLASH_FORCE (which is useful while the sandbox is
+    // off by default).
+    if (Preferences::GetBool("security.sandbox.mac.flash.enabled") ||
+        PR_GetEnv("MOZ_SANDBOX_MAC_FLASH_FORCE")) {
+      mSandboxLevel = 1;
+
+      // Enable sandbox logging in the plugin process if it has
+      // been turned on via prefs or environment variables.
+      if (Preferences::GetBool("security.sandbox.logging.enabled") ||
+          PR_GetEnv("MOZ_SANDBOX_LOGGING") ||
+          PR_GetEnv("MOZ_SANDBOX_MAC_FLASH_LOGGING")) {
+            mIsSandboxLoggingEnabled = true;
+      }
+    }
+  }
+#endif
 }
 
 #if !defined(XP_WIN) && !defined(XP_MACOSX)
 static void
 ConvertToUTF8(nsCString& aString)
 {
   Unused << UTF_8_ENCODING->DecodeWithoutBOMHandling(aString, aString);
 }
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -168,16 +168,17 @@ public:
   PRLibrary     *mLibrary;
   RefPtr<nsNPAPIPlugin> mPlugin;
   bool          mIsFlashPlugin;
   bool          mSupportsAsyncRender;
   nsCString     mFullPath; // UTF-8
   int64_t       mLastModifiedTime;
   nsCOMPtr<nsITimer> mUnloadTimer;
   int32_t       mSandboxLevel;
+  bool          mIsSandboxLoggingEnabled;
 
   void          InvalidateBlocklistState();
 
 private:
   virtual ~nsPluginTag();
 
   nsCString     mNiceFileName; // UTF-8
   uint16_t      mCachedBlocklistState;
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -49,16 +49,20 @@
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
 #include "ChildProfilerController.h"
 #endif
 
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+#include "mozilla/Sandbox.h"
+#endif
+
 using namespace mozilla;
 using namespace mozilla::ipc;
 using namespace mozilla::plugins;
 using namespace mozilla::widget;
 
 #if defined(XP_WIN)
 const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
 #endif
@@ -94,16 +98,20 @@ PluginModuleChild::PluginModuleChild(boo
 #elif defined(MOZ_WIDGET_GTK)
   , mNestedLoopTimerId(0)
 #endif
 #ifdef OS_WIN
   , mNestedEventHook(nullptr)
   , mGlobalCallWndProcHook(nullptr)
   , mAsyncRenderSupport(false)
 #endif
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+  , mEnableFlashSandbox(false)
+  , mEnableFlashSandboxLogging(false)
+#endif
 {
     memset(&mFunctions, 0, sizeof(mFunctions));
     if (mIsChrome) {
         MOZ_ASSERT(!gChromeInstance);
         gChromeInstance = this;
     }
 
 #ifdef XP_MACOSX
@@ -186,16 +194,25 @@ PluginModuleChild::RecvDisableFlashProte
 #ifdef XP_WIN
     FunctionHook::HookProtectedMode();
 #else
     MOZ_ASSERT(false, "Should not be called");
 #endif
     return IPC_OK();
 }
 
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+void
+PluginModuleChild::EnableFlashSandbox(bool aShouldEnableLogging)
+{
+    mEnableFlashSandbox = true;
+    mEnableFlashSandboxLogging = aShouldEnableLogging;
+}
+#endif
+
 bool
 PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
                                  base::ProcessId aParentPid,
                                  MessageLoop* aIOLoop,
                                  IPC::Channel* aChannel)
 {
     NS_ASSERTION(aChannel, "need a channel");
 
@@ -279,16 +296,32 @@ PluginModuleChild::InitForChrome(const s
         (NP_PLUGININIT)PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
     NS_ENSURE_TRUE(mInitializeFunc, false);
 #else
 
 #  error Please copy the initialization code from nsNPAPIPlugin.cpp
 
 #endif
 
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+    if (mEnableFlashSandbox) {
+      MacSandboxInfo flashSandboxInfo;
+      flashSandboxInfo.type = MacSandboxType_Plugin;
+      flashSandboxInfo.pluginInfo.type = MacSandboxPluginType_Flash;
+      flashSandboxInfo.pluginInfo.pluginBinaryPath = aPluginFilename;
+      flashSandboxInfo.shouldLog = mEnableFlashSandboxLogging;
+
+      std::string sbError;
+      if (!mozilla::StartMacSandbox(flashSandboxInfo, sbError)) {
+          fprintf(stderr, "Failed to start sandbox:\n%s\n", sbError.c_str());
+          return false;
+      }
+    }
+#endif
+
     return true;
 }
 
 #if defined(MOZ_WIDGET_GTK)
 
 typedef void (*GObjectDisposeFn)(GObject*);
 typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -308,17 +308,27 @@ public: // called by PluginInstanceChild
      * is destroyed. This function will remove the object from mObjectMap.
      */
     static void DeallocNPObject(NPObject* o);
 
     NPError NPP_Destroy(PluginInstanceChild* instance) {
         return mFunctions.destroy(instance->GetNPP(), 0);
     }
 
+#if defined(OS_MACOSX) && defined(MOZ_SANDBOX)
+    void EnableFlashSandbox(bool aShouldEnableLogging);
+#endif
+
 private:
+
+#if defined(OS_MACOSX) && defined(MOZ_SANDBOX)
+    bool mEnableFlashSandbox;
+    bool mEnableFlashSandboxLogging;
+#endif
+
 #if defined(OS_WIN)
     virtual void EnteredCall() override;
     virtual void ExitedCall() override;
 
     // Entered/ExitedCall notifications keep track of whether the plugin has
     // entered a nested event loop within this interrupt call.
     struct IncallFrame
     {
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -467,17 +467,18 @@ PluginModuleChromeParent::LoadModule(con
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
 
     nsAutoPtr<PluginModuleChromeParent> parent(
             new PluginModuleChromeParent(aFilePath, aPluginId,
                                          aPluginTag->mSandboxLevel));
     UniquePtr<LaunchCompleteTask> onLaunchedRunnable(new LaunchedTask(parent));
     bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable),
-                                                aPluginTag->mSandboxLevel);
+                                                aPluginTag->mSandboxLevel,
+                                                aPluginTag->mIsSandboxLoggingEnabled);
     if (!launched) {
         // We never reached open
         parent->mShutdown = true;
         return nullptr;
     }
     parent->mIsFlashPlugin = aPluginTag->mIsFlashPlugin;
     uint32_t blocklistState;
     nsresult rv = aPluginTag->GetBlocklistState(&blocklistState);
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -91,16 +91,26 @@ PluginProcessChild::Init(int aArgc, char
     // NB: need to be very careful in ensuring that the first arg
     // (after the binary name) here is indeed the plugin module path.
     // Keep in sync with dom/plugins/PluginModuleParent.
     std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
     MOZ_ASSERT(values.size() >= 2, "not enough args");
 
     pluginFilename = UnmungePluginDsoPath(values[1]);
 
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+    if (values.size() >= 3 && values[2] == "-flashSandbox") {
+      bool enableLogging = false;
+      if (values.size() >= 4 && values[3] == "-flashSandboxLogging") {
+        enableLogging = true;
+      }
+      mPlugin.EnableFlashSandbox(enableLogging);
+    }
+#endif
+
 #elif defined(OS_WIN)
     std::vector<std::wstring> values =
         CommandLine::ForCurrentProcess()->GetLooseValues();
     MOZ_ASSERT(values.size() >= 1, "not enough loose args");
 
     if (ShouldProtectPluginCurrentDirectory(values[0].c_str())) {
         SanitizeEnvironmentVariables();
         SetDllDirectory(L"");
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -47,32 +47,47 @@ PluginProcessParent::~PluginProcessParen
             sPidSet = nullptr;
         }
     }
 #endif
 }
 
 bool
 PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
-                            int32_t aSandboxLevel)
+                            int32_t aSandboxLevel,
+                            bool aIsSandboxLoggingEnabled)
 {
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
+    // At present, the Mac Flash plugin sandbox does not support different
+    // levels and is enabled via a boolean pref or environment variable.
+    // On Mac, when |aSandboxLevel| is positive, we enable the sandbox.
+#if defined(XP_WIN)
     mSandboxLevel = aSandboxLevel;
+#endif // XP_WIN
 #else
     if (aSandboxLevel != 0) {
         MOZ_ASSERT(false,
                    "Can't enable an NPAPI process sandbox for platform/build.");
     }
 #endif
 
     mLaunchCompleteTask = mozilla::Move(aLaunchCompleteTask);
 
     vector<string> args;
     args.push_back(MungePluginDsoPath(mPluginFilePath));
 
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+    if (aSandboxLevel > 0) {
+        args.push_back("-flashSandbox");
+        if (aIsSandboxLoggingEnabled) {
+            args.push_back("-flashSandboxLogging");
+        }
+    }
+#endif
+
     bool result = AsyncLaunch(args);
     if (!result) {
         mLaunchCompleteTask = nullptr;
     }
     return result;
 }
 
 void
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -50,19 +50,22 @@ public:
     /**
      * Launch the plugin process. If the process fails to launch,
      * this method will return false.
      *
      * @param aLaunchCompleteTask Task that is executed on the main
      * thread once the asynchonous launch has completed.
      * @param aSandboxLevel Determines the strength of the sandbox.
      * <= 0 means no sandbox.
+     * @param aIsSandboxLoggingEnabled Indicates if sandbox violation
+     * logging should be enabled for the plugin process.
      */
     bool Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask = UniquePtr<LaunchCompleteTask>(),
-                int32_t aSandboxLevel = 0);
+                int32_t aSandboxLevel = 0,
+                bool aIsSandboxLoggingEnabled = false);
 
     void Delete();
 
     virtual bool CanShutdown() override
     {
         return true;
     }
 
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -18,16 +18,17 @@ enum MacSandboxType {
 };
 
 enum MacSandboxPluginType {
   MacSandboxPluginType_Default = 0,
   MacSandboxPluginType_GMPlugin_Default,      // Any Gecko Media Plugin
   MacSandboxPluginType_GMPlugin_OpenH264,     // Gecko Media Plugin, OpenH264
   MacSandboxPluginType_GMPlugin_EME,          // Gecko Media Plugin, EME
   MacSandboxPluginType_GMPlugin_EME_Widevine, // Gecko Media Plugin, Widevine
+  MacSandboxPluginType_Flash,                 // Flash
   MacSandboxPluginType_Invalid
 };
 
 typedef struct _MacSandboxPluginInfo {
   _MacSandboxPluginInfo()
     : type(MacSandboxPluginType_Default) {}
   _MacSandboxPluginInfo(const struct _MacSandboxPluginInfo& other)
     : type(other.type), pluginPath(other.pluginPath),
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -125,18 +125,66 @@ OSXVersion::GetVersionNumber()
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo const &aInfo, std::string &aErrorMessage)
 {
   std::vector<const char *> params;
   std::string profile;
   std::string macOSMinor = std::to_string(OSXVersion::OSXVersionMinor());
 
-  if (aInfo.type == MacSandboxType_Plugin) {
-    profile = pluginSandboxRules;
+  // Used for the Flash sandbox. Declared here so that they
+  // stay in scope until sandbox_init_with_parameters is called.
+  std::string flashCacheDir, flashTempDir, flashPath;
+
+  if (aInfo.type == MacSandboxType_Plugin &&
+      aInfo.pluginInfo.type == MacSandboxPluginType_Flash) {
+    profile = flashPluginSandboxRules;
+
+    params.push_back("SHOULD_LOG");
+    params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
+
+    params.push_back("MAC_OS_MINOR");
+    params.push_back(macOSMinor.c_str());
+
+    params.push_back("HOME_PATH");
+    params.push_back(getenv("HOME"));
+
+    params.push_back("PLUGIN_BINARY_PATH");
+    flashPath = realpath(aInfo.pluginInfo.pluginBinaryPath.c_str(), nullptr);
+    if (flashPath.empty()) {
+      return false;
+    }
+    params.push_back(flashPath.c_str());
+
+    // User cache dir
+    params.push_back("DARWIN_USER_CACHE_DIR");
+    char cacheDir[PATH_MAX];
+    if (!confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDir, sizeof(cacheDir))) {
+      return false;
+    }
+    flashCacheDir = realpath(cacheDir, nullptr);
+    if (flashCacheDir.empty()) {
+      return false;
+    }
+    params.push_back(flashCacheDir.c_str());
+
+    // User temp dir
+    params.push_back("DARWIN_USER_TEMP_DIR");
+    char tempDir[PATH_MAX];
+    if (!confstr(_CS_DARWIN_USER_TEMP_DIR, tempDir, sizeof(tempDir))) {
+      return false;
+    }
+    flashTempDir = realpath(tempDir, nullptr);
+    if (flashTempDir.empty()) {
+      return false;
+    }
+    params.push_back(flashTempDir.c_str());
+  }
+  else if (aInfo.type == MacSandboxType_Plugin) {
+    profile = const_cast<char *>(pluginSandboxRules);
     params.push_back("SHOULD_LOG");
     params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
     params.push_back("PLUGIN_BINARY_PATH");
     params.push_back(aInfo.pluginInfo.pluginBinaryPath.c_str());
     params.push_back("APP_PATH");
     params.push_back(aInfo.appPath.c_str());
     params.push_back("APP_BINARY_PATH");
     params.push_back(aInfo.appBinaryPath.c_str());
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -3,17 +3,17 @@
  * 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_SandboxPolicies_h
 #define mozilla_SandboxPolicies_h
 
 namespace mozilla {
 
-static const char pluginSandboxRules[] = R"(
+static const char pluginSandboxRules[] = R"SANDBOX_LITERAL(
   (version 1)
 
   (define should-log (param "SHOULD_LOG"))
   (define plugin-binary-path (param "PLUGIN_BINARY_PATH"))
   (define app-path (param "APP_PATH"))
   (define app-binary-path (param "APP_BINARY_PATH"))
 
   (if (string=? should-log "TRUE")
@@ -30,23 +30,23 @@ static const char pluginSandboxRules[] =
       (literal "/usr/share/icu/icudt51l.dat")
       (subpath "/System/Library/Displays/Overrides")
       (subpath "/System/Library/CoreServices/CoreTypes.bundle")
       (subpath "/System/Library/PrivateFrameworks")
       (regex #"^/usr/lib/libstdc\+\+\.[^/]*dylib$")
       (literal plugin-binary-path)
       (literal app-path)
       (literal app-binary-path))
-)";
+)SANDBOX_LITERAL";
 
-static const char widevinePluginSandboxRulesAddend[] = R"(
+static const char widevinePluginSandboxRulesAddend[] = R"SANDBOX_LITERAL(
   (allow mach-lookup (global-name "com.apple.windowserver.active"))
-)";
+)SANDBOX_LITERAL";
 
-static const char contentSandboxRules[] = R"(
+static const char contentSandboxRules[] = R"SANDBOX_LITERAL(
   (version 1)
 
   (define should-log (param "SHOULD_LOG"))
   (define sandbox-level-1 (param "SANDBOX_LEVEL_1"))
   (define sandbox-level-2 (param "SANDBOX_LEVEL_2"))
   (define sandbox-level-3 (param "SANDBOX_LEVEL_3"))
   (define macosMinorVersion (string->number (param "MAC_OS_MINOR")))
   (define appPath (param "APP_PATH"))
@@ -347,47 +347,345 @@ static const char contentSandboxRules[] 
     (subpath "/Library/Application Support/Apple/Fonts")
     (home-subpath "/Library/Fonts")
     ; Allow read access to paths allowed via sandbox extensions.
     ; This is needed for fonts in non-standard locations normally
     ; due to third party font managers. The extensions are
     ; automatically issued by the font server in response to font
     ; API calls.
     (extension "com.apple.app-sandbox.read"))
-)";
+)SANDBOX_LITERAL";
 
 // These are additional rules that are added to the content process rules for
 // file content processes.
-static const char fileContentProcessAddend[] = R"(
+static const char fileContentProcessAddend[] = R"SANDBOX_LITERAL(
   ; This process has blanket file read privileges
   (allow file-read*)
 
   ; File content processes need access to iconservices to draw file icons in
   ; directory listings
   (allow mach-lookup (global-name "com.apple.iconservices"))
-)";
+)SANDBOX_LITERAL";
 
 // These are additional rules that are added to the content process rules when
 // audio remoting is not enabled. (Once audio remoting is always used these
 // will be deleted.)
-static const char contentProcessAudioAddend[] = R"(
+static const char contentProcessAudioAddend[] = R"SANDBOX_LITERAL(
   (allow ipc-posix-shm-read* ipc-posix-shm-write-data
     (ipc-posix-name-regex #"^AudioIO"))
 
   (allow mach-lookup
     (global-name "com.apple.audio.coreaudiod")
     (global-name "com.apple.audio.audiohald"))
 
   (if (>= macosMinorVersion 13)
     (allow mach-lookup
-      ; bug 1376163
-      (global-name "com.apple.audio.AudioComponentRegistrar")))
+    ; bug 1376163
+    (global-name "com.apple.audio.AudioComponentRegistrar")))
 
   (allow iokit-open (iokit-user-client-class "IOAudioEngineUserClient"))
 
   (allow file-read* (subpath "/Library/Audio/Plug-Ins"))
 
   (allow device-microphone)
-)";
+)SANDBOX_LITERAL";
+
+// The "Safe Mode" Flash NPAPI plugin process profile
+static const char flashPluginSandboxRules[] = R"SANDBOX_LITERAL(
+  (version 1)
+
+  ; Parameters
+  (define shouldLog (param "SHOULD_LOG"))
+  (define macosMinorVersion (string->number (param "MAC_OS_MINOR")))
+  (define homeDir (param "HOME_PATH"))
+  (define cacheDir (param "DARWIN_USER_CACHE_DIR"))
+  (define tempDir (param "DARWIN_USER_TEMP_DIR"))
+  (define pluginPath (param "PLUGIN_BINARY_PATH"))
+
+  (if (string=? shouldLog "TRUE")
+      (deny default)
+      (deny default (with no-log)))
+  (debug deny)
+  (allow system-audit file-read-metadata)
+  ; These are not included in (deny default)
+  (deny process-info*)
+  ; This isn't available in some older macOS releases.
+  (if (defined? 'nvram*)
+    (deny nvram*))
+
+  ; Allow read access to standard system paths.
+  (allow file-read*
+    (require-all (file-mode #o0004)
+      (require-any
+        (subpath "/System")
+        (subpath "/usr/lib")
+        (subpath "/Library/Filesystems/NetFSPlugins")
+        (subpath "/Library/GPUBundles")
+        (subpath "/usr/share"))))
+  (allow file-read-metadata
+         (literal "/etc")
+         (literal "/tmp")
+         (literal "/var")
+         (literal "/private/etc/localtime"))
+  (allow file-read*
+         (literal "/dev/autofs_nowait")
+         (literal "/dev/random")
+         (literal "/dev/urandom"))
+  (allow file-read*
+         file-write-data
+         (literal "/dev/null")
+         (literal "/dev/zero"))
+  (allow file-read*
+         file-write-data
+         file-ioctl
+         (literal "/dev/dtracehelper"))
+
+  ; Graphics
+  (allow user-preference-read
+         (preference-domain "com.apple.opengl")
+         (preference-domain "com.nvidia.OpenGL"))
+  (allow mach-lookup
+         (global-name "com.apple.cvmsServ"))
+  (allow iokit-open
+         (iokit-connection "IOAccelerator")
+         (iokit-user-client-class "IOAccelerationUserClient")
+         (iokit-user-client-class "IOSurfaceRootUserClient")
+         (iokit-user-client-class "IOSurfaceSendRight"))
+  (allow iokit-open
+         (iokit-user-client-class "AppleIntelMEUserClient")
+         (iokit-user-client-class "AppleSNBFBUserClient"))
+  (allow iokit-open
+         (iokit-user-client-class "AGPMClient")
+         (iokit-user-client-class "AppleGraphicsControlClient")
+         (iokit-user-client-class "AppleGraphicsPolicyClient"))
+
+  ; Network
+  (allow file-read*
+         (literal "/Library/Preferences/com.apple.networkd.plist"))
+  (allow mach-lookup
+         (global-name "com.apple.SystemConfiguration.PPPController")
+         (global-name "com.apple.SystemConfiguration.SCNetworkReachability")
+         (global-name "com.apple.nehelper")
+         (global-name "com.apple.networkd")
+         (global-name "com.apple.nsurlstorage-cache")
+         (global-name "com.apple.symptomsd")
+         (global-name "com.apple.usymptomsd"))
+  (allow network-outbound
+         (control-name "com.apple.netsrc")
+         (control-name "com.apple.network.statistics"))
+  (allow system-socket
+         (require-all (socket-domain AF_SYSTEM)
+                      (socket-protocol 2)) ; SYSPROTO_CONTROL
+         (socket-domain AF_ROUTE))
+  (allow network-outbound
+      (literal "/private/var/run/mDNSResponder")
+      (literal "/private/var/run/asl_input")
+      (literal "/private/var/run/syslog")
+      (remote tcp)
+      (remote udp))
+  (allow network-inbound
+      (local udp))
+
+  (allow process-info-pidinfo)
+  (allow process-info-setcontrol (target self))
+
+  ; macOS 10.9 does not support the |sysctl-name| predicate
+  (if (= macosMinorVersion 9)
+      (allow sysctl-read)
+      (allow sysctl-read
+        (sysctl-name
+          "hw.availcpu"
+          "hw.physicalcpu_max"
+          "hw.ncpu"
+          "hw.model"
+          "hw.busfrequency_max"
+          "hw.cpu64bit_capable"
+          "hw.optional.x86_64"
+          "kern.memorystatus_level"
+          "kern.osrelease"
+          "kern.hostname"
+          "kern.maxfilesperproc"
+          "vm.footprint_suspend")))
+
+  ; Utilities for allowing access to home subdirectories
+  (define home-library-path
+    (string-append homeDir "/Library"))
+
+  (define home-library-prefs-path
+    (string-append homeDir "/Library" "/Preferences"))
+
+  (define (home-literal home-relative-literal)
+    (literal (string-append homeDir home-relative-literal)))
+
+  (define (home-library-regex home-library-relative-regex)
+    (regex (string-append "^" (regex-quote home-library-path))
+           home-library-relative-regex))
+
+  (define (home-library-subpath home-library-relative-subpath)
+      (subpath (string-append home-library-path home-library-relative-subpath)))
+
+  (define (home-library-literal home-library-relative-literal)
+      (literal (string-append home-library-path home-library-relative-literal)))
+
+  (define (home-library-preferences-literal
+           home-library-preferences-relative-literal)
+      (literal (string-append home-library-prefs-path
+                home-library-preferences-relative-literal)))
+
+  ; Read-only paths
+  (allow file-read*
+      (literal "/")
+      (literal "/private/etc/services")
+      (literal "/private/etc/resolv.conf")
+      (literal "/private/var/run/resolv.conf")
+      (subpath "/Library/Frameworks")
+      (subpath "/Library/Managed Preferences")
+      (home-literal "/.CFUserTextEncoding")
+      (home-library-subpath "/Audio")
+      (home-library-subpath "/ColorPickers")
+      (home-library-subpath "/ColorSync")
+      (subpath "/Library/Components")
+      (home-library-subpath "/Components")
+      (subpath "/Library/Contextual Menu Items")
+      (subpath "/Library/Input Methods")
+      (home-library-subpath "/Input Methods")
+      (subpath "/Library/InputManagers")
+      (home-library-subpath "/InputManagers")
+      (home-library-subpath "/KeyBindings")
+      (subpath "/Library/Keyboard Layouts")
+      (home-library-subpath "/Keyboard Layouts")
+      (subpath "/Library/Spelling")
+      (home-library-subpath "/Spelling")
+      (home-library-literal "/Caches/com.apple.coreaudio.components.plist")
+      (subpath "/Library/Audio/Sounds")
+      (subpath "/Library/Audio/Plug-Ins/Components")
+      (home-library-subpath "/Audio/Plug-Ins/Components")
+      (subpath "/Library/Audio/Plug-Ins/HAL")
+      (subpath "/Library/CoreMediaIO/Plug-Ins/DAL")
+      (subpath "/Library/QuickTime")
+      (home-library-subpath "/QuickTime")
+      (subpath "/Library/Video/Plug-Ins")
+      (home-library-subpath "/Caches/QuickTime")
+      (subpath "/Library/ColorSync")
+      (home-literal "/Library/Preferences/com.apple.lookup.shared.plist"))
+
+  (allow iokit-open
+      (iokit-user-client-class "IOAudioControlUserClient")
+      (iokit-user-client-class "IOAudioEngineUserClient")
+      (iokit-user-client-class "IOHIDParamUserClient")
+      (iokit-user-client-class "RootDomainUserClient"))
+
+  ; Services
+  (allow mach-lookup
+      (global-name "com.apple.audio.AudioComponentRegistrar")
+      (global-name "com.apple.DiskArbitration.diskarbitrationd")
+      (global-name "com.apple.ImageCaptureExtension2.presence")
+      (global-name "com.apple.PowerManagement.control")
+      (global-name "com.apple.SecurityServer")
+      (global-name "com.apple.SystemConfiguration.PPPController")
+      (global-name "com.apple.SystemConfiguration.configd")
+      (global-name "com.apple.UNCUserNotification")
+      (global-name "com.apple.audio.audiohald")
+      (global-name "com.apple.audio.coreaudiod")
+      (global-name "com.apple.cfnetwork.AuthBrokerAgent")
+      (global-name "com.apple.FontObjectsServer")
+      (global-name "com.apple.fonts")
+      (global-name "com.apple.lsd.mapdb")
+      (global-name "com.apple.pasteboard.1") ; Allows paste into input field
+      (global-name "com.apple.dock.server")
+      (global-name "com.apple.dock.fullscreen")
+      (global-name "com.apple.coreservices.appleevents")
+      (global-name "com.apple.coreservices.launchservicesd")
+      (global-name "com.apple.window_proxies")
+      (local-name "com.apple.tsm.portname")
+      (global-name "com.apple.axserver")
+      (global-name "com.apple.pbs.fetch_services")
+      (global-name "com.apple.tccd.system")
+      (global-name "com.apple.tsm.uiserver")
+      (global-name "com.apple.inputmethodkit.launchagent")
+      (global-name "com.apple.inputmethodkit.launcher")
+      (global-name "com.apple.inputmethodkit.getxpcendpoint")
+      (global-name "com.apple.decalog4.incoming")
+      (global-name "com.apple.windowserver.active"))
+
+  ; Fonts
+  (allow file-read*
+    (subpath "/Library/Fonts")
+    (subpath "/Library/Application Support/Apple/Fonts")
+    (home-library-subpath "/Fonts")
+    ; Allow read access to paths allowed via sandbox extensions.
+    ; This is needed for fonts in non-standard locations normally
+    ; due to third party font managers. The extensions are
+    ; automatically issued by the font server in response to font
+    ; API calls.
+    (extension "com.apple.app-sandbox.read"))
+
+  (allow ipc-posix-shm*
+      (ipc-posix-name-regex #"^AudioIO")
+      (ipc-posix-name-regex #"^CFPBS:"))
+
+  (allow ipc-posix-shm-read*
+      (ipc-posix-name-regex #"^/tmp/com\.apple\.csseed\.")
+      (ipc-posix-name "FNetwork.defaultStorageSession")
+      (ipc-posix-name "apple.shm.notification_center"))
+
+  ; Printing
+  (allow network-outbound (literal "/private/var/run/cupsd"))
+  (allow mach-lookup
+      (global-name "com.apple.printuitool.agent")
+      (global-name "com.apple.printtool.agent")
+      (global-name "com.apple.printtool.daemon"))
+  (allow file-read*
+      (subpath "/Library/Printers")
+      (home-literal "/.cups/lpoptions")
+      (home-literal "/.cups/client.conf")
+      (literal "/private/etc/cups/client.conf")
+      (literal "/private/etc/cups/lpoptions")
+      (subpath "/private/etc/cups/ppd")
+      (literal "/private/var/run/cupsd"))
+  (allow user-preference-read
+      (preference-domain "org.cups.PrintingPrefs"))
+
+  ; Camera/Mic
+  (allow device-camera)
+  (allow device-microphone)
+
+  ; Path to the plugin binary, user cache dir, and user temp dir
+  (allow file-read* (subpath pluginPath))
+  (allow file-read* file-write* (subpath cacheDir))
+  (allow file-read* file-write* (subpath tempDir))
+
+  ; Per Adobe, needed for Flash LocalConnection functionality
+  (allow ipc-posix-sem
+      (ipc-posix-name "MacromediaSemaphoreDig"))
+
+  ; Flash debugger and enterprise deployment config files
+  (allow file-read*
+      (home-literal "/mm.cfg")
+      (home-literal "/mms.cfg"))
+
+  (deny file-read-xattr
+      (home-library-literal "/Caches")
+      (home-library-preferences-literal "/"))
+
+  (allow file-read* file-write-create file-write-mode file-write-owner
+      (home-library-literal "/Caches/Adobe")
+      (home-library-preferences-literal "/Macromedia"))
+
+  (allow file-read* file-write*
+      (literal "/Library/Application Support/Macromedia/mms.cfg")
+      (home-library-literal "/Application Support/Macromedia/mms.cfg")
+      (home-library-subpath "/Caches/Adobe/Flash Player")
+      (home-library-subpath "/Preferences/Macromedia/Flash Player"))
+
+  (allow file-read*
+      (literal "/Library/PreferencePanes/Flash Player.prefPane")
+      (home-library-literal "/PreferencePanes/Flash Player.prefPane")
+      (home-library-regex "/Application Support/Macromedia/ss\.(cfg|cfn|sgn)$"))
+
+  (allow network-bind (local ip))
+
+  (deny file-write-create (vnode-type SYMLINK))
+)SANDBOX_LITERAL";
 
 }
 
 #endif // mozilla_SandboxPolicies_h