Bug 1359566 - remove permissions related to audio from the macOS content process sandbox when cubeb remoting is enabled; r?haik draft
authorAlex Gaynor <agaynor@mozilla.com>
Thu, 21 Dec 2017 09:59:47 -0500
changeset 748907 eea158d91c5217e88e2473337484b281f54dada5
parent 748783 9746e0a0a81cc089ff65e30ae902864846cd1b94
push id97267
push userbmo:agaynor@mozilla.com
push dateTue, 30 Jan 2018 17:19:53 +0000
reviewershaik
bugs1359566
milestone60.0a1
Bug 1359566 - remove permissions related to audio from the macOS content process sandbox when cubeb remoting is enabled; r?haik MozReview-Commit-ID: BmBNuSlsyBH
dom/ipc/ContentChild.cpp
security/sandbox/mac/Sandbox.h
security/sandbox/mac/Sandbox.mm
security/sandbox/mac/SandboxPolicies.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1581,16 +1581,17 @@ StartMacOSContentSandbox()
   info.level = sandboxLevel;
   info.hasFilePrivileges = isFileProcess;
   info.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
                    PR_GetEnv("MOZ_SANDBOX_LOGGING");
   info.appPath.assign(appPath.get());
   info.appBinaryPath.assign(appBinaryPath.get());
   info.appDir.assign(appDir.get());
   info.appTempDir.assign(tempDirPath.get());
+  info.hasAudio = !Preferences::GetBool("media.cubeb.sandbox");
 
   // These paths are used to whitelist certain directories used by the testing
   // system. They should not be considered a public API, and are only intended
   // for use in automation.
   nsAutoCString testingReadPath1;
   Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
                           testingReadPath1);
   if (!testingReadPath1.IsEmpty()) {
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -42,16 +42,17 @@ typedef struct _MacSandboxInfo {
     : type(MacSandboxType_Default), level(0), hasFilePrivileges(false),
       shouldLog(true) {}
   _MacSandboxInfo(const struct _MacSandboxInfo& other) = default;
 
   MacSandboxType type;
   int32_t level;
   bool hasFilePrivileges;
   bool hasSandboxedProfile;
+  bool hasAudio;
   MacSandboxPluginInfo pluginInfo;
   std::string appPath;
   std::string appBinaryPath;
   std::string appDir;
   std::string appTempDir;
   std::string profileDir;
   std::string debugWriteDir;
 
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -122,44 +122,38 @@ OSXVersion::GetVersionNumber()
   return mOSXVersion;
 }
 
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo const &aInfo, std::string &aErrorMessage)
 {
   std::vector<const char *> params;
-  char *profile = NULL;
-  bool profile_needs_free = false;
-
+  std::string profile;
   std::string macOSMinor = std::to_string(OSXVersion::OSXVersionMinor());
 
   if (aInfo.type == MacSandboxType_Plugin) {
-    profile = const_cast<char *>(pluginSandboxRules);
+    profile = 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());
 
     if (aInfo.pluginInfo.type == MacSandboxPluginType_GMPlugin_EME_Widevine) {
-      char *widevineProfile = NULL;
-      asprintf(&widevineProfile, "%s%s", profile,
-        widevinePluginSandboxRulesAddend);
-      profile = widevineProfile;
-      profile_needs_free = true;
+      profile.append(widevinePluginSandboxRulesAddend);
     }
   }
   else if (aInfo.type == MacSandboxType_Content) {
     MOZ_ASSERT(aInfo.level >= 1);
     if (aInfo.level >= 1) {
-      profile = const_cast<char *>(contentSandboxRules);
+      profile = contentSandboxRules;
       params.push_back("SHOULD_LOG");
       params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
       params.push_back("SANDBOX_LEVEL_1");
       params.push_back(aInfo.level == 1 ? "TRUE" : "FALSE");
       params.push_back("SANDBOX_LEVEL_2");
       params.push_back(aInfo.level == 2 ? "TRUE" : "FALSE");
       params.push_back("SANDBOX_LEVEL_3");
       params.push_back(aInfo.level == 3 ? "TRUE" : "FALSE");
@@ -198,21 +192,20 @@ bool StartMacSandbox(MacSandboxInfo cons
 #ifdef DEBUG
       if (!aInfo.debugWriteDir.empty()) {
         params.push_back("DEBUG_WRITE_DIR");
         params.push_back(aInfo.debugWriteDir.c_str());
       }
 #endif // DEBUG
 
       if (aInfo.hasFilePrivileges) {
-        char *fileContentProfile = NULL;
-        asprintf(&fileContentProfile, "%s%s", profile,
-          fileContentProcessAddend);
-        profile = fileContentProfile;
-        profile_needs_free = true;
+        profile.append(fileContentProcessAddend);
+      }
+      if (aInfo.hasAudio) {
+        profile.append(contentProcessAudioAddend);
       }
     } else {
       fprintf(stderr,
         "Content sandbox disabled due to sandbox level setting\n");
       return false;
     }
   }
   else {
@@ -220,55 +213,52 @@ bool StartMacSandbox(MacSandboxInfo cons
     asprintf(&msg, "Unexpected sandbox type %u", aInfo.type);
     if (msg) {
       aErrorMessage.assign(msg);
       free(msg);
     }
     return false;
   }
 
-  if (!profile) {
+  if (profile.empty()) {
     fprintf(stderr, "Out of memory in StartMacSandbox()!\n");
     return false;
   }
 
 // In order to avoid relying on any other Mozilla modules (as described at the
 // top of this file), we use our own #define instead of the existing MOZ_LOG
 // infrastructure. This can be used by developers to debug the macOS sandbox
 // policy.
 #define MAC_SANDBOX_PRINT_POLICY 0
 #if MAC_SANDBOX_PRINT_POLICY
   printf("Sandbox params:\n");
   for (size_t i = 0; i < params.size() / 2; i++) {
     printf("  %s = %s\n", params[i * 2], params[(i * 2) + 1]);
   }
-  printf("Sandbox profile:\n%s\n", profile);
+  printf("Sandbox profile:\n%s\n", profile.c_str());
 #endif
 
   // The parameters array is null terminated.
   params.push_back(nullptr);
 
   char *errorbuf = NULL;
-  int rv = sandbox_init_with_parameters(profile, 0, params.data(),
+  int rv = sandbox_init_with_parameters(profile.c_str(), 0, params.data(),
                                         &errorbuf);
   if (rv) {
     if (errorbuf) {
       char *msg = NULL;
       asprintf(&msg, "sandbox_init() failed with error \"%s\"", errorbuf);
       if (msg) {
         aErrorMessage.assign(msg);
         free(msg);
       }
-      fprintf(stderr, "profile: %s\n", profile);
+      fprintf(stderr, "profile: %s\n", profile.c_str());
       sandbox_free_error(errorbuf);
     }
   }
-  if (profile_needs_free) {
-    free(profile);
-  }
   if (rv) {
     return false;
   }
 
   return true;
 }
 
 } // namespace mozilla
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -178,40 +178,31 @@ static const char contentSandboxRules[] 
     (subpath (string-append profileDir profile-relative-subpath)))
 
   (define (allow-shared-list domain)
     (allow file-read*
            (home-regex (string-append "/Library/Preferences/" (regex-quote domain)))))
 
   (allow ipc-posix-shm-read-data ipc-posix-shm-write-data
     (ipc-posix-name-regex #"^CFPBS:"))
-  (allow ipc-posix-shm-read* ipc-posix-shm-write-data
-    (ipc-posix-name-regex #"^AudioIO"))
 
   (allow signal (target self))
 
-  (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 1392988
       (xpc-service-name "com.apple.coremedia.videodecoder")
       (xpc-service-name "com.apple.coremedia.videoencoder")))
 
 ; bug 1312273
   (if (= macosMinorVersion 9)
      (allow mach-lookup (global-name "com.apple.xpcd")))
 
   (allow iokit-open
-     (iokit-user-client-class "IOHIDParamUserClient")
-     (iokit-user-client-class "IOAudioEngineUserClient"))
+     (iokit-user-client-class "IOHIDParamUserClient"))
 
   ; Only supported on macOS 10.10+
   (if (defined? 'iokit-get-properties)
     (allow iokit-get-properties
       (iokit-property "board-id")
       (iokit-property "IODVDBundleName")
       (iokit-property "IOGLBundleName")
       (iokit-property "IOGVACodec")
@@ -225,17 +216,16 @@ static const char contentSandboxRules[] 
 ; depending on systems, the 1st, 2nd or both rules are necessary
   (allow user-preference-read (preference-domain "com.apple.HIToolbox"))
   (allow file-read-data (literal "/Library/Preferences/com.apple.HIToolbox.plist"))
 
   (allow user-preference-read (preference-domain "com.apple.ATS"))
   (allow file-read-data (literal "/Library/Preferences/.GlobalPreferences.plist"))
 
   (allow file-read*
-      (subpath "/Library/Audio/Plug-Ins")
       (subpath "/Library/Spelling")
       (literal "/")
       (literal "/private/tmp")
       (literal "/private/var/tmp")
       (home-literal "/.CFUserTextEncoding")
       (home-literal "/Library/Preferences/com.apple.DownloadAssessment.plist")
       (home-subpath "/Library/Colors")
       (home-subpath "/Library/Keyboard Layouts")
@@ -276,20 +266,16 @@ static const char contentSandboxRules[] 
       (allow file-write-data (subpath debugWriteDir))
       (allow file-write-create
         (require-all
           (subpath debugWriteDir)
           (vnode-type REGULAR-FILE)))))
 
   (allow-shared-list "org.mozilla.plugincontainer")
 
-; the following rule should be removed when microphone access
-; is brokered through the content process
-  (allow device-microphone)
-
 ; Per-user and system-wide Extensions dir
   (allow file-read*
       (home-regex "/Library/Application Support/[^/]+/Extensions/")
       (regex "^/Library/Application Support/[^/]+/Extensions/"))
 
 ; bug 1393805
   (allow file-read*
       (home-subpath "/Library/Application Support/Mozilla/SystemExtensionsDev"))
@@ -363,21 +349,45 @@ static const char contentSandboxRules[] 
     ; 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"))
 )";
 
+// These are additional rules that are added to the content process rules for
+// file content processes.
 static const char fileContentProcessAddend[] = R"(
   ; 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"))
 )";
 
+// 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"(
+  (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")))
+
+  (allow iokit-open (iokit-user-client-class "IOAudioEngineUserClient"))
+
+  (allow file-read* (subpath "/Library/Audio/Plug-Ins"))
+
+  (allow device-microphone)
+)";
 
 }
 
 #endif // mozilla_SandboxPolicies_h