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 11:44:27 +0000
changeset 243025 2ab5add95717
parent 243024 64fb35ee1af6
child 243026 f7b5148c84a1
push id4366
push userbobowencode@gmail.com
push date2015-01-26 12:06 +0000
treeherdermozilla-beta@9bfc57be3f2c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh, tabraldes, sledru
bugs1123245
milestone36.0
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
@@ -780,69 +780,65 @@ 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 (!mEnableContentSandbox) {
         break;
       }
       if (!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
         mSandboxBroker.SetSecurityLevelForContentProcess(mWarnOnlyContentSandbox);
         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
@@ -103,21 +103,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;