Bug 1123245 Part 1: Enable an open sandbox on Windows NPAPI processes. r=josh, r=tabraldes, a=sledru
authorBob Owen <bobowencode@gmail.com>
Mon, 26 Jan 2015 08:00:06 +0000
changeset 251095 20dbbb1fd98a238e51b7ea4e0400914867e0a50b
parent 251094 3ba70e3d1e0dd20a9ed88ebd4658d0ebf8d64bf6
child 251096 f79836f9957ea6066370fedc8601c17ed916b81f
push id698
push userjlund@mozilla.com
push dateMon, 23 Mar 2015 22:08:11 +0000
treeherdermozilla-release@b0c0ae7b02a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh, tabraldes, sledru
bugs1123245
milestone37.0a2
Bug 1123245 Part 1: Enable an open sandbox on Windows NPAPI processes. r=josh, r=tabraldes, a=sledru
dom/plugins/ipc/PluginProcessChild.cpp
ipc/glue/GeckoChildProcessHost.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -7,27 +7,32 @@
 #include "mozilla/ipc/IOThreadChild.h"
 #include "mozilla/plugins/PluginProcessChild.h"
 
 #include "prlink.h"
 
 #include "base/command_line.h"
 #include "base/string_util.h"
 #include "chrome/common/chrome_switches.h"
+#include "nsDebugImpl.h"
 
 #if defined(XP_MACOSX)
 #include "nsCocoaFeatures.h"
 // An undocumented CoreGraphics framework method, present in the same form
 // since at least OS X 10.5.
 extern "C" CGError CGSSetDebugOptions(int options);
 #endif
 
 #ifdef XP_WIN
 #include <objbase.h>
 bool ShouldProtectPluginCurrentDirectory(char16ptr_t pluginFilePath);
+#if defined(MOZ_SANDBOX)
+#define TARGET_SANDBOX_EXPORTS
+#include "mozilla/sandboxTarget.h"
+#endif
 #endif
 
 using mozilla::ipc::IOThreadChild;
 
 #ifdef OS_WIN
 #include "nsSetDllDirectory.h"
 #include <algorithm>
 
@@ -44,16 +49,18 @@ std::size_t caseInsensitiveFind(std::str
 
 namespace mozilla {
 namespace plugins {
 
 
 bool
 PluginProcessChild::Init()
 {
+    nsDebugImpl::SetMultiprocessMode("NPAPI");
+
 #if defined(XP_MACOSX)
     // Remove the trigger for "dyld interposing" that we added in
     // GeckoChildProcessHost::PerformAsyncLaunchInternal(), in the host
     // process just before we were launched.  Dyld interposing will still
     // happen in our process (the plugin child process).  But we don't want
     // it to happen in any processes that the plugin might launch from our
     // process.
     nsCString interpose(PR_GetEnv("DYLD_INSERT_LIBRARIES"));
@@ -112,16 +119,23 @@ PluginProcessChild::Init()
     NS_ABORT_IF_FALSE(values.size() >= 1, "not enough loose args");
 
     if (ShouldProtectPluginCurrentDirectory(values[0].c_str())) {
         SanitizeEnvironmentVariables();
         SetDllDirectory(L"");
     }
 
     pluginFilename = WideToUTF8(values[0]);
+
+#if defined(MOZ_SANDBOX)
+    // This is probably the earliest we would want to start the sandbox.
+    // As we attempt to tighten the sandbox, we may need to consider moving this
+    // to later in the plugin initialization.
+    mozilla::SandboxTarget::Instance()->StartSandbox();
+#endif
 #else
 #  error Sorry
 #endif
 
     if (NS_FAILED(nsRegion::InitStatic())) {
       NS_ERROR("Could not initialize nsRegion");
       return false;
     }
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -795,66 +795,62 @@ GeckoChildProcessHost::PerformAsyncLaunc
     }
     file = Omnijar::GetPath(Omnijar::APP);
     if (file && NS_SUCCEEDED(file->GetPath(path))) {
       cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
       cmdLine.AppendLooseValue(path.get());
     }
   }
 
-#if defined(XP_WIN)
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
   bool shouldSandboxCurrentProcess = false;
   switch (mProcessType) {
     case GeckoProcessType_Content:
 #if defined(MOZ_CONTENT_SANDBOX)
       if (!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
         mSandboxBroker.SetSecurityLevelForContentProcess(mMoreStrictContentSandbox);
         cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
         shouldSandboxCurrentProcess = true;
       }
 #endif // MOZ_CONTENT_SANDBOX
       break;
     case GeckoProcessType_Plugin:
-      // XXX: We don't sandbox this process type yet
-      // mSandboxBroker.SetSecurityLevelForPluginProcess();
-      // cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
-      // shouldSandboxCurrentProcess = true;
+      if (!PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
+        mSandboxBroker.SetSecurityLevelForPluginProcess();
+        cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
+        shouldSandboxCurrentProcess = true;
+      }
       break;
     case GeckoProcessType_IPDLUnitTest:
       // XXX: We don't sandbox this process type yet
       // mSandboxBroker.SetSecurityLevelForIPDLUnitTestProcess();
       // cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
       // shouldSandboxCurrentProcess = true;
       break;
     case GeckoProcessType_GMPlugin:
-#ifdef MOZ_SANDBOX
       if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
         mSandboxBroker.SetSecurityLevelForGMPlugin();
         cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
         shouldSandboxCurrentProcess = true;
       }
-#endif
       break;
     case GeckoProcessType_Default:
     default:
       MOZ_CRASH("Bad process type in GeckoChildProcessHost");
       break;
   };
 
-#ifdef MOZ_SANDBOX
   if (shouldSandboxCurrentProcess) {
     for (auto it = mAllowedFilesRead.begin();
          it != mAllowedFilesRead.end();
          ++it) {
       mSandboxBroker.AllowReadFile(it->c_str());
     }
   }
-#endif
-
-#endif // XP_WIN
+#endif // XP_WIN && MOZ_SANDBOX
 
   // Add the application directory path (-appdir path)
   AddAppDirToCommandLine(cmdLine);
 
   // XXX Command line params past this point are expected to be at
   // the end of the command line string, and in a specific order.
   // See XRE_InitChildProcess in nsEmbedFunction.
 
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -118,21 +118,35 @@ SandboxBroker::SetSecurityLevelForConten
 
 bool
 SandboxBroker::SetSecurityLevelForPluginProcess()
 {
   if (!mPolicy) {
     return false;
   }
 
-  auto result = mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
+  auto result = mPolicy->SetJobLevel(sandbox::JOB_NONE,
+                                     0 /* ui_exceptions */);
   bool ret = (sandbox::SBOX_ALL_OK == result);
-  result = mPolicy->SetTokenLevel(sandbox::USER_UNPROTECTED,
-                                  sandbox::USER_UNPROTECTED);
+
+  result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+                                  sandbox::USER_RESTRICTED_SAME_ACCESS);
+  ret = ret && (sandbox::SBOX_ALL_OK == result);
+
+  result = mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_MEDIUM);
   ret = ret && (sandbox::SBOX_ALL_OK == result);
+
+  // Add the policy for the client side of a pipe. It is just a file
+  // in the \pipe\ namespace. We restrict it to pipes that start with
+  // "chrome." so the sandboxed process cannot connect to system services.
+  result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+                            sandbox::TargetPolicy::FILES_ALLOW_ANY,
+                            L"\\??\\pipe\\chrome.*");
+  ret = ret && (sandbox::SBOX_ALL_OK == result);
+
   return ret;
 }
 
 bool
 SandboxBroker::SetSecurityLevelForIPDLUnitTestProcess()
 {
   if (!mPolicy) {
     return false;