From c43bf02cdaf01b257ec7c6394cdf2799b16e96fb Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Sun, 15 May 2016 16:35:22 +0100 Subject: [PATCH] Bug 1035125 Part 8: Pass sandboxing pointers through XRE_InitChildProcess instead of linking to more functions in xul. r=aklotz,glandium MozReview-Commit-ID: 5AiktOArpfU --HG-- extra : rebase_source : 1ba3be949e2bfeb3b67687ab05d43342852ab764 --- dom/media/gmp/GMPLoader.cpp | 6 +-- dom/media/gmp/GMPLoader.h | 3 +- ipc/contentproc/plugin-container.cpp | 28 ++++------ mozglue/android/APKOpen.cpp | 4 +- .../sandbox/win/loggingCallbacks.h | 45 +++------------- .../sandbox/win/sandboxLogging.h | 8 +-- security/sandbox/moz.build | 2 + .../sandbox/win/SandboxInitialization.cpp | 46 +++++++++++++++++ security/sandbox/win/SandboxInitialization.h | 35 +++++++++++++ .../win/src/sandboxtarget/sandboxTarget.h | 9 +--- toolkit/xre/moz.build | 6 +++ toolkit/xre/nsEmbedFunctions.cpp | 19 ++++--- xpcom/build/XREChildData.h | 51 +++++++++++++++++++ xpcom/build/moz.build | 1 + xpcom/build/nsXULAppAPI.h | 3 +- 15 files changed, 182 insertions(+), 84 deletions(-) create mode 100644 security/sandbox/win/SandboxInitialization.cpp create mode 100644 security/sandbox/win/SandboxInitialization.h create mode 100644 xpcom/build/XREChildData.h diff --git a/dom/media/gmp/GMPLoader.cpp b/dom/media/gmp/GMPLoader.cpp index 9de1fd869ac9..8d9fd96f8b79 100644 --- a/dom/media/gmp/GMPLoader.cpp +++ b/dom/media/gmp/GMPLoader.cpp @@ -7,11 +7,9 @@ #include "GMPLoader.h" #include #include "mozilla/Attributes.h" -#include "mozilla/UniquePtr.h" #include "gmp-entrypoints.h" #include "prlink.h" #include "prenv.h" -#include "nsAutoPtr.h" #include @@ -79,8 +77,8 @@ private: UniquePtr mAdapter; }; -GMPLoader* CreateGMPLoader(SandboxStarter* aStarter) { - return static_cast(new GMPLoaderImpl(aStarter)); +UniquePtr CreateGMPLoader(SandboxStarter* aStarter) { + return MakeUnique(aStarter); } class PassThroughGMPAdapter : public GMPAdapter { diff --git a/dom/media/gmp/GMPLoader.h b/dom/media/gmp/GMPLoader.h index 7b022bc1ca1c..b159ad58c61b 100644 --- a/dom/media/gmp/GMPLoader.h +++ b/dom/media/gmp/GMPLoader.h @@ -10,6 +10,7 @@ #include #include "prlink.h" #include "gmp-entrypoints.h" +#include "mozilla/UniquePtr.h" #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) #include "mozilla/Sandbox.h" @@ -98,7 +99,7 @@ public: // On Desktop, this function resides in plugin-container. // On Mobile, this function resides in XUL. -GMPLoader* CreateGMPLoader(SandboxStarter* aStarter); +UniquePtr CreateGMPLoader(SandboxStarter* aStarter); } // namespace gmp } // namespace mozilla diff --git a/ipc/contentproc/plugin-container.cpp b/ipc/contentproc/plugin-container.cpp index 45f02eb98082..6119996baff0 100644 --- a/ipc/contentproc/plugin-container.cpp +++ b/ipc/contentproc/plugin-container.cpp @@ -25,9 +25,8 @@ #include "GMPLoader.h" #if defined(XP_WIN) && defined(MOZ_SANDBOX) -#include "mozilla/sandboxTarget.h" -#include "mozilla/sandboxing/loggingCallbacks.h" -#include "sandbox/win/src/sandbox_factory.h" +#include "mozilla/sandboxing/SandboxInitialization.h" +#include "mozilla/sandboxing/sandboxLogging.h" #endif #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) @@ -86,7 +85,7 @@ class WinSandboxStarter : public mozilla::gmp::SandboxStarter { public: virtual bool Start(const char *aLibPath) override { if (gIsSandboxEnabled) { - sandbox::SandboxFactory::GetTargetServices()->LowerToken(); + mozilla::sandboxing::LowerSandbox(); } return true; } @@ -163,21 +162,17 @@ content_process_main(int argc, char* argv[]) #endif } + XREChildData childData; + #if defined(XP_WIN) && defined(MOZ_SANDBOX) if (gIsSandboxEnabled) { - sandbox::TargetServices* target_service = - sandbox::SandboxFactory::GetTargetServices(); - if (!target_service) { + childData.sandboxTargetServices = + mozilla::sandboxing::GetInitializedTargetServices(); + if (!childData.sandboxTargetServices) { return 1; } - sandbox::ResultCode result = target_service->Init(); - if (result != sandbox::SBOX_ALL_OK) { - return 2; - } - - mozilla::SandboxTarget::Instance()->SetTargetServices(target_service); - mozilla::sandboxing::PrepareForLogging(); + childData.ProvideLogFunction = mozilla::sandboxing::ProvideLogFunction; } #endif @@ -225,16 +220,15 @@ content_process_main(int argc, char* argv[]) SetDllDirectory(L""); } #endif - nsAutoPtr loader; #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) // On desktop, the GMPLoader lives in plugin-container, so that its // code can be covered by an EME/GMP vendor's voucher. nsAutoPtr starter(MakeSandboxStarter()); if (XRE_GetProcessType() == GeckoProcessType_GMPlugin) { - loader = mozilla::gmp::CreateGMPLoader(starter); + childData.gmpLoader = mozilla::gmp::CreateGMPLoader(starter); } #endif - nsresult rv = XRE_InitChildProcess(argc, argv, loader); + nsresult rv = XRE_InitChildProcess(argc, argv, &childData); NS_ENSURE_SUCCESS(rv, 1); return 0; diff --git a/mozglue/android/APKOpen.cpp b/mozglue/android/APKOpen.cpp index 99ae61506910..2f3c8eef71c0 100644 --- a/mozglue/android/APKOpen.cpp +++ b/mozglue/android/APKOpen.cpp @@ -35,6 +35,7 @@ #include "mozilla/TimeStamp.h" #include "mozilla/UniquePtr.h" +#include "XREChildData.h" /* Android headers don't define RUSAGE_THREAD */ #ifndef RUSAGE_THREAD @@ -421,6 +422,7 @@ ChildProcessInit(int argc, char* argv[]) fXRE_SetProcessType(argv[--argc]); - return fXRE_InitChildProcess(argc, argv, nullptr); + XREChildData childData; + return fXRE_InitChildProcess(argc, argv, &childData); } diff --git a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h index 5ce5689bde6c..4e6d443b53b7 100644 --- a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h +++ b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h @@ -7,53 +7,20 @@ #ifndef security_sandbox_loggingCallbacks_h__ #define security_sandbox_loggingCallbacks_h__ -#include "mozilla/sandboxing/loggingTypes.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -#ifdef TARGET_SANDBOX_EXPORTS #include #include #include "mozilla/Preferences.h" +#include "mozilla/sandboxing/loggingTypes.h" #include "nsContentUtils.h" #ifdef MOZ_STACKWALKING #include "mozilla/StackWalk.h" #endif -#define TARGET_SANDBOX_EXPORT __declspec(dllexport) -#else -#define TARGET_SANDBOX_EXPORT __declspec(dllimport) -#endif - namespace mozilla { namespace sandboxing { -// We need to use a callback to work around the fact that sandbox_s lib is -// linked into plugin-container.exe directly and also via xul.dll via -// sandboxbroker.dll. This causes problems with holding the state required to -// implement sandbox logging. -// So, we provide a callback from plugin-container.exe that the code in xul.dll -// can call to make sure we hit the right version of the code. -void TARGET_SANDBOX_EXPORT -SetProvideLogFunctionCb(ProvideLogFunctionCb aProvideLogFunctionCb); - -// Provide a call back so a pointer to a logging function can be passed later. -static void -PrepareForLogging() -{ - SetProvideLogFunctionCb(ProvideLogFunction); -} - -#ifdef TARGET_SANDBOX_EXPORTS -static ProvideLogFunctionCb sProvideLogFunctionCb = nullptr; - -void -SetProvideLogFunctionCb(ProvideLogFunctionCb aProvideLogFunctionCb) -{ - sProvideLogFunctionCb = aProvideLogFunctionCb; -} - #ifdef MOZ_STACKWALKING static uint32_t sStackTraceDepth = 0; @@ -110,15 +77,15 @@ Log(const char* aMessageType, // Initialize sandbox logging if required. static void -InitLoggingIfRequired() +InitLoggingIfRequired(ProvideLogFunctionCb aProvideLogFunctionCb) { - if (!sProvideLogFunctionCb) { + if (!aProvideLogFunctionCb) { return; } if (Preferences::GetBool("security.sandbox.windows.log") || PR_GetEnv("MOZ_WIN_SANDBOX_LOGGING")) { - sProvideLogFunctionCb(Log); + aProvideLogFunctionCb(Log); #if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_STACKWALKING) // We can only log the stack trace on process types where we know that the @@ -130,8 +97,8 @@ InitLoggingIfRequired() #endif } } -#endif + } // sandboxing } // mozilla -#endif // security_sandbox_loggingCallbacks_h__ +#endif // security_sandbox_loggingCallbacks_h__ \ No newline at end of file diff --git a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h index d5ebdffd7b7e..32228a315e8a 100644 --- a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h +++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h @@ -13,12 +13,6 @@ #include "loggingTypes.h" -#ifdef SANDBOX_EXPORTS -#define SANDBOX_EXPORT __declspec(dllexport) -#else -#define SANDBOX_EXPORT __declspec(dllimport) -#endif - namespace sandbox { class TargetPolicy; } @@ -28,7 +22,7 @@ namespace sandboxing { // This is used to pass a LogCallback to the sandboxing code, as the logging // requires code to which we cannot link directly. -void SANDBOX_EXPORT ProvideLogFunction(LogFunction aLogFunction); +void ProvideLogFunction(LogFunction aLogFunction); // Set up dummy interceptions via the broker, so we can log calls. void ApplyLoggingPolicy(sandbox::TargetPolicy& aPolicy); diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index bc1e12e51236..92fad603e79f 100644 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -28,6 +28,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT': 'chromium-shim/sandbox/win/loggingCallbacks.h', 'chromium-shim/sandbox/win/loggingTypes.h', 'chromium-shim/sandbox/win/sandboxLogging.h', + 'win/SandboxInitialization.h', ] SOURCES += [ @@ -128,6 +129,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT': 'chromium/sandbox/win/src/win2k_threadpool.cc', 'chromium/sandbox/win/src/win_utils.cc', 'chromium/sandbox/win/src/window.cc', + 'win/SandboxInitialization.cpp', ] if CONFIG['CPU_ARCH'] == 'x86_64': diff --git a/security/sandbox/win/SandboxInitialization.cpp b/security/sandbox/win/SandboxInitialization.cpp new file mode 100644 index 000000000000..58f168430803 --- /dev/null +++ b/security/sandbox/win/SandboxInitialization.cpp @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 "SandboxInitialization.h" + +#include "sandbox/win/src/sandbox_factory.h" + +namespace mozilla { +namespace sandboxing { + +static sandbox::TargetServices* +InitializeTargetServices() +{ + sandbox::TargetServices* targetServices = + sandbox::SandboxFactory::GetTargetServices(); + if (!targetServices) { + return nullptr; + } + + if (targetServices->Init() != sandbox::SBOX_ALL_OK) { + return nullptr; + } + + return targetServices; +} + +sandbox::TargetServices* +GetInitializedTargetServices() +{ + static sandbox::TargetServices* sInitializedTargetServices = + InitializeTargetServices(); + + return sInitializedTargetServices; +} + +void +LowerSandbox() +{ + GetInitializedTargetServices()->LowerToken(); +} + +} // sandboxing +} // mozilla diff --git a/security/sandbox/win/SandboxInitialization.h b/security/sandbox/win/SandboxInitialization.h new file mode 100644 index 000000000000..a889926279cc --- /dev/null +++ b/security/sandbox/win/SandboxInitialization.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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_sandboxing_SandboxInitialization_h +#define mozilla_sandboxing_SandboxInitialization_h + +namespace sandbox { +class TargetServices; +} + +namespace mozilla { +// Note the Chromium code just uses a bare sandbox namespace, which makes using +// sandbox for our namespace painful. +namespace sandboxing { + +/** + * Initializes (if required) and returns the Chromium sandbox TargetServices. + * + * @return the TargetServices or null if the creation or initialization failed. + */ +sandbox::TargetServices* GetInitializedTargetServices(); + +/** + * Lowers the permissions on the process sandbox. + * Provided because the GMP sandbox needs to be lowered from the executable. + */ +void LowerSandbox(); + +} // sandboxing +} // mozilla + +#endif // mozilla_sandboxing_SandboxInitialization_h diff --git a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h index 50ac15283e21..f46a2ce707bb 100644 --- a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h +++ b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h @@ -12,17 +12,10 @@ #include "mozilla/Assertions.h" #include "base/MissingBasicTypes.h" #include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/target_services.h" -#ifdef TARGET_SANDBOX_EXPORTS -#define TARGET_SANDBOX_EXPORT __declspec(dllexport) -#else -#define TARGET_SANDBOX_EXPORT __declspec(dllimport) -#endif namespace mozilla { - -class TARGET_SANDBOX_EXPORT SandboxTarget +class SandboxTarget { public: /** diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build index 28a86f3bcd29..a4313f1813e0 100644 --- a/toolkit/xre/moz.build +++ b/toolkit/xre/moz.build @@ -159,6 +159,12 @@ LOCAL_INCLUDES += [ '/xpcom/build', ] +if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT': + LOCAL_INCLUDES += [ + '/security/sandbox/chromium', + '/security/sandbox/chromium-shim', + ] + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': LOCAL_INCLUDES += [ '/widget', diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index aa86cd8a0c0f..3cebee77d543 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -79,7 +79,7 @@ #include "base/histogram.h" #if defined(MOZ_SANDBOX) && defined(XP_WIN) -#define TARGET_SANDBOX_EXPORTS +#include "mozilla/sandboxTarget.h" #include "mozilla/sandboxing/loggingCallbacks.h" #endif @@ -297,11 +297,12 @@ SetTaskbarGroupId(const nsString& aId) nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], - GMPLoader* aGMPLoader) + const XREChildData* aChildData) { NS_ENSURE_ARG_MIN(aArgc, 2); NS_ENSURE_ARG_POINTER(aArgv); NS_ENSURE_ARG_POINTER(aArgv[0]); + MOZ_ASSERT(aChildData); #ifdef HAS_DLL_BLOCKLIST DllBlocklist_Initialize(); @@ -314,13 +315,13 @@ XRE_InitChildProcess(int aArgc, #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) // On non-Fennec Gecko, the GMPLoader code resides in plugin-container, // and we must forward it through to the GMP code here. - GMPProcessChild::SetGMPLoader(aGMPLoader); + GMPProcessChild::SetGMPLoader(aChildData->gmpLoader.get()); #else // On Fennec, the GMPLoader's code resides inside XUL (because for the time // being GMPLoader relies upon NSPR, which we can't use in plugin-container // on Android), so we create it here inside XUL and pass it to the GMP code. - nsAutoPtr loader(CreateGMPLoader(nullptr)); - GMPProcessChild::SetGMPLoader(loader); + UniquePtr loader = CreateGMPLoader(nullptr); + GMPProcessChild::SetGMPLoader(loader.get()); #endif #if defined(XP_WIN) @@ -345,6 +346,12 @@ XRE_InitChildProcess(int aArgc, if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1) freopen("CONIN$", "r", stdin); } + +#if defined(MOZ_SANDBOX) + if (aChildData->sandboxTargetServices) { + SandboxTarget::Instance()->SetTargetServices(aChildData->sandboxTargetServices); + } +#endif #endif // NB: This must be called before profiler_init @@ -628,7 +635,7 @@ XRE_InitChildProcess(int aArgc, #if defined(MOZ_SANDBOX) && defined(XP_WIN) // We need to do this after the process has been initialised, as // InitLoggingIfRequired may need access to prefs. - mozilla::sandboxing::InitLoggingIfRequired(); + mozilla::sandboxing::InitLoggingIfRequired(aChildData->ProvideLogFunction); #endif OverrideDefaultLocaleIfNeeded(); diff --git a/xpcom/build/XREChildData.h b/xpcom/build/XREChildData.h new file mode 100644 index 000000000000..487fede940a1 --- /dev/null +++ b/xpcom/build/XREChildData.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 XREChildData_h +#define XREChildData_h + +#include "mozilla/UniquePtr.h" + +#if defined(XP_WIN) && defined(MOZ_SANDBOX) +#include "mozilla/sandboxing/loggingTypes.h" + +namespace sandbox { +class TargetServices; +} +#endif + +namespace mozilla { +namespace gmp { +class GMPLoader; +} +} + +/** + * Data needed to start a child process. + */ +struct XREChildData +{ +#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) + /** + * Used to load the GMP binary. + */ + mozilla::UniquePtr gmpLoader; +#endif + +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + /** + * Chromium sandbox TargetServices. + */ + sandbox::TargetServices* sandboxTargetServices = nullptr; + + /** + * Function to provide a logging function to the chromium sandbox code. + */ + mozilla::sandboxing::ProvideLogFunctionCb ProvideLogFunction = nullptr; +#endif +}; + +#endif // XREChildData_h diff --git a/xpcom/build/moz.build b/xpcom/build/moz.build index 0fd6737fd8e4..7336284df900 100644 --- a/xpcom/build/moz.build +++ b/xpcom/build/moz.build @@ -10,6 +10,7 @@ EXPORTS += [ 'nsXPCOMCIDInternal.h', 'nsXREAppData.h', 'nsXULAppAPI.h', + 'XREChildData.h', 'xrecore.h', ] diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index bd87549251d6..86daded43773 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -19,6 +19,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Vector.h" #include "mozilla/TimeStamp.h" +#include "XREChildData.h" /** * A directory service key which provides the platform-correct "application @@ -411,7 +412,7 @@ class GMPLoader; XRE_API(nsresult, XRE_InitChildProcess, (int aArgc, char* aArgv[], - mozilla::gmp::GMPLoader* aGMPLoader)) + const XREChildData* aChildData)) XRE_API(GeckoProcessType, XRE_GetProcessType, ())