From 844fdf04ebc8737ca20dd4769d0a92653328955f Mon Sep 17 00:00:00 2001 From: Steven Michaud Date: Fri, 8 Aug 2014 11:55:22 -0500 Subject: [PATCH] Bug 1012949 - Sandbox the OpenH264 plugin for Mac r=rjesup,areinald,ted a=PatchNeedsToLandToday --- configure.in | 3 + content/media/gmp/GMPChild.cpp | 112 +++++++++++++++++++++++--------- content/media/gmp/GMPChild.h | 8 +++ security/sandbox/mac/Sandbox.h | 46 +++++++++++++ security/sandbox/mac/Sandbox.mm | 72 ++++++++++++++++++++ security/sandbox/mac/moz.build | 15 +++++ security/sandbox/moz.build | 4 +- 7 files changed, 228 insertions(+), 32 deletions(-) create mode 100644 security/sandbox/mac/Sandbox.h create mode 100644 security/sandbox/mac/Sandbox.mm create mode 100644 security/sandbox/mac/moz.build diff --git a/configure.in b/configure.in index 6cf00af6b83f..8c1b0c3bcd19 100644 --- a/configure.in +++ b/configure.in @@ -6397,6 +6397,9 @@ Linux) ;; esac ;; +Darwin) + MOZ_GMP_SANDBOX=1 + ;; esac if test -n "$MOZ_GMP_SANDBOX"; then diff --git a/content/media/gmp/GMPChild.cpp b/content/media/gmp/GMPChild.cpp index d0780dff02c9..1c5f9bb31dc9 100644 --- a/content/media/gmp/GMPChild.cpp +++ b/content/media/gmp/GMPChild.cpp @@ -27,9 +27,11 @@ using mozilla::dom::CrashReporterChild; #if defined(XP_WIN) #define TARGET_SANDBOX_EXPORTS #include "mozilla/sandboxTarget.h" -#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) +#elif defined (MOZ_GMP_SANDBOX) +#if defined(XP_LINUX) || defined(XP_MACOSX) #include "mozilla/Sandbox.h" #endif +#endif namespace mozilla { namespace gmp { @@ -45,34 +47,9 @@ GMPChild::~GMPChild() { } -void -GMPChild::CheckThread() -{ - MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current()); -} - -bool -GMPChild::Init(const std::string& aPluginPath, - base::ProcessHandle aParentProcessHandle, - MessageLoop* aIOLoop, - IPC::Channel* aChannel) -{ - if (!Open(aChannel, aParentProcessHandle, aIOLoop)) { - return false; - } - -#ifdef MOZ_CRASHREPORTER - SendPCrashReporterConstructor(CrashReporter::CurrentThreadId()); -#endif -#if defined(XP_WIN) - mozilla::SandboxTarget::Instance()->StartSandbox(); -#endif - - return LoadPluginLibrary(aPluginPath); -} - -bool -GMPChild::LoadPluginLibrary(const std::string& aPluginPath) +static bool +GetPluginBinaryPath(const std::string& aPluginPath, + nsCString &aPluginBinaryPath) { nsDependentCString pluginPath(aPluginPath.c_str()); @@ -99,8 +76,83 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath) #endif libFile->AppendRelativePath(binaryName); + libFile->GetNativePath(aPluginBinaryPath); + return true; +} + +#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) +void +GMPChild::OnChannelConnected(int32_t aPid) +{ + MacSandboxInfo info; + info.type = MacSandboxType_Plugin; + info.pluginInfo.type = MacSandboxPluginType_GMPlugin_Default; + info.pluginInfo.pluginPath.Assign(mPluginPath.c_str()); + + nsAutoCString pluginBinaryPath; + if (!GetPluginBinaryPath(mPluginPath, pluginBinaryPath)) { + MOZ_CRASH("Error scanning plugin path"); + } + mPluginBinaryPath.Assign(pluginBinaryPath); + info.pluginInfo.pluginBinaryPath.Assign(pluginBinaryPath); + + nsAutoCString err; + if (!mozilla::StartMacSandbox(info, err)) { + NS_WARNING(err.get()); + MOZ_CRASH("sandbox_init() failed"); + } + + if (!LoadPluginLibrary(mPluginPath)) { + err.AppendPrintf("Failed to load GMP plugin \"%s\"", + mPluginPath.c_str()); + NS_WARNING(err.get()); + MOZ_CRASH("Failed to load GMP plugin"); + } +} +#endif // XP_MACOSX && MOZ_GMP_SANDBOX + +void +GMPChild::CheckThread() +{ + MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current()); +} + +bool +GMPChild::Init(const std::string& aPluginPath, + base::ProcessHandle aParentProcessHandle, + MessageLoop* aIOLoop, + IPC::Channel* aChannel) +{ + if (!Open(aChannel, aParentProcessHandle, aIOLoop)) { + return false; + } + +#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) + mPluginPath = aPluginPath; + return true; +#endif + +#ifdef MOZ_CRASHREPORTER + SendPCrashReporterConstructor(CrashReporter::CurrentThreadId()); +#endif +#if defined(XP_WIN) + mozilla::SandboxTarget::Instance()->StartSandbox(); +#endif + + return LoadPluginLibrary(aPluginPath); +} + +bool +GMPChild::LoadPluginLibrary(const std::string& aPluginPath) +{ nsAutoCString nativePath; - libFile->GetNativePath(nativePath); +#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) + nativePath.Assign(mPluginBinaryPath); +#else + if (!GetPluginBinaryPath(aPluginPath, nativePath)) { + return false; + } +#endif #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) // Enable sandboxing here -- we know the plugin file's path, but diff --git a/content/media/gmp/GMPChild.h b/content/media/gmp/GMPChild.h index dd453cde4050..d01f1b031dd5 100644 --- a/content/media/gmp/GMPChild.h +++ b/content/media/gmp/GMPChild.h @@ -22,6 +22,10 @@ public: GMPChild(); virtual ~GMPChild(); +#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) + void OnChannelConnected(int32_t aPid); +#endif + bool Init(const std::string& aPluginPath, base::ProcessHandle aParentProcessHandle, MessageLoop* aIOLoop, @@ -68,6 +72,10 @@ private: PRLibrary* mLib; GMPGetAPIFunc mGetAPIFunc; MessageLoop* mGMPMessageLoop; +#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) + std::string mPluginPath; + nsCString mPluginBinaryPath; +#endif }; } // namespace gmp diff --git a/security/sandbox/mac/Sandbox.h b/security/sandbox/mac/Sandbox.h new file mode 100644 index 000000000000..023cb830c55d --- /dev/null +++ b/security/sandbox/mac/Sandbox.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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_Sandbox_h +#define mozilla_Sandbox_h + +#include "nsString.h" + +enum MacSandboxType { + MacSandboxType_Default = 0, + MacSandboxType_Plugin, + MacSandboxType_Invalid +}; + +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_Invalid +}; + +typedef struct _MacSandboxPluginInfo { + _MacSandboxPluginInfo() + : type(MacSandboxPluginType_Default) {} + MacSandboxPluginType type; + nsCString pluginPath; + nsCString pluginBinaryPath; +} MacSandboxPluginInfo; + +typedef struct _MacSandboxInfo { + _MacSandboxInfo() + : type(MacSandboxType_Default) {} + MacSandboxType type; + MacSandboxPluginInfo pluginInfo; +} MacSandboxInfo; + +namespace mozilla { + +bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage); + +} // namespace mozilla + +#endif // mozilla_Sandbox_h diff --git a/security/sandbox/mac/Sandbox.mm b/security/sandbox/mac/Sandbox.mm new file mode 100644 index 000000000000..a3c90f3ef4e8 --- /dev/null +++ b/security/sandbox/mac/Sandbox.mm @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "Sandbox.h" + +#include "nsCocoaFeatures.h" + +// XXX There are currently problems with the /usr/include/sandbox.h file on +// some/all of the Macs in Mozilla's build system. For the time being (until +// this problem is resolved), we refer directly to what we need from it, +// rather than including it here. +extern "C" int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); +extern "C" void sandbox_free_error(char *errorbuf); + +namespace mozilla { + +static const char *rules = + "(version 1)\n" + "(deny default)\n" + "(allow signal (target self))\n" + "(allow sysctl-read)\n" + // Needed only on OS X 10.6 + "%s(allow file-read-data (literal \"%s\"))\n" + "(allow mach-lookup\n" + " (global-name \"com.apple.cfprefsd.agent\")\n" + " (global-name \"com.apple.cfprefsd.daemon\")\n" + " (global-name \"com.apple.system.opendirectoryd.libinfo\")\n" + " (global-name \"com.apple.system.logger\")\n" + " (global-name \"com.apple.ls.boxd\"))\n" + "(allow file-read*\n" + " (regex #\"^/etc$\")\n" + " (regex #\"^/dev/u?random$\")\n" + " (regex #\"^/(private/)?var($|/)\")\n" + " (regex #\"\\.app/Contents/MacOS/plugin-container\\.app/Contents/\")\n" + " (literal \"/usr/share/icu/icudt51l.dat\")\n" + " (literal \"%s\"))\n"; + +bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage) +{ + if (!aInfo.type == MacSandboxType_Plugin) { + aErrorMessage.AppendPrintf("Unexpected sandbox type %u", aInfo.type); + return false; + } + + nsAutoCString profile; + if (nsCocoaFeatures::OnLionOrLater()) { + profile.AppendPrintf(rules, ";", + aInfo.pluginInfo.pluginPath.get(), + aInfo.pluginInfo.pluginBinaryPath.get()); + } else { + profile.AppendPrintf(rules, "", + aInfo.pluginInfo.pluginPath.get(), + aInfo.pluginInfo.pluginBinaryPath.get()); + } + + char *errorbuf = NULL; + if (sandbox_init(profile.get(), 0, &errorbuf)) { + if (errorbuf) { + aErrorMessage.AppendPrintf("sandbox_init() failed with error \"%s\"", + errorbuf); + printf(profile.get()); + sandbox_free_error(errorbuf); + } + return false; + } + + return true; +} + +} // namespace mozilla diff --git a/security/sandbox/mac/moz.build b/security/sandbox/mac/moz.build new file mode 100644 index 000000000000..87f70cc1a589 --- /dev/null +++ b/security/sandbox/mac/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXPORTS.mozilla += [ + 'Sandbox.h', +] + +SOURCES += [ + 'Sandbox.mm', +] + +FINAL_LIBRARY = 'xul' diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index 8766a11ae596..f472a1759e69 100644 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -5,9 +5,9 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. if CONFIG['OS_ARCH'] == 'Linux': - DIRS += ['linux'] - +elif CONFIG['OS_ARCH'] == 'Darwin': + DIRS += ['mac'] elif CONFIG['OS_ARCH'] == 'WINNT': LIBRARY_NAME = 'sandbox_s' FORCE_STATIC_LIB = True