Bug 1399787 - Part 9. Sandbox the PDFium process. draft
authorcku <cku@mozilla.com>
Wed, 18 Oct 2017 20:52:45 +0800
changeset 710605 6ee4003807cbcf7e0a5b7df83471df2e38a3599a
parent 710604 8d83f08b89f3d3c4e0a5c0a5f1e8791c53219a9c
child 710606 1da7c93de088dfc746f05ae33ad41610292c06d0
push id92855
push usercku@mozilla.com
push dateMon, 11 Dec 2017 02:44:26 +0000
bugs1399787
milestone59.0a1
Bug 1399787 - Part 9. Sandbox the PDFium process. MozReview-Commit-ID: 6ED7EPZvOMR
ipc/glue/GeckoChildProcessHost.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.h
widget/windows/PDFiumProcessChild.cpp
widget/windows/PDFiumProcessChild.h
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -935,16 +935,27 @@ GeckoChildProcessHost::PerformAsyncLaunc
           !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
         bool ok = mSandboxBroker.SetSecurityLevelForPluginProcess(mSandboxLevel);
         if (!ok) {
           return false;
         }
         shouldSandboxCurrentProcess = true;
       }
       break;
+#ifdef MOZ_ENABLE_SKIA_PDF
+    case GeckoProcessType_PDFium:
+      if (!PR_GetEnv("MOZ_DISABLE_PDFIUM_SANDBOX")) {
+        bool ok = mSandboxBroker.SetSecurityLevelForPDFiumProcess();
+        if (!ok) {
+          return false;
+        }
+        shouldSandboxCurrentProcess = true;
+      }
+      break;
+#endif
     case GeckoProcessType_IPDLUnitTest:
       // XXX: We don't sandbox this process type yet
       break;
     case GeckoProcessType_GMPlugin:
       if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
         // The Widevine CDM on Windows can only load at USER_RESTRICTED,
         // not at USER_LOCKDOWN. So look in the command line arguments
         // to see if we're loading the path to the Widevine CDM, and if
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -843,16 +843,95 @@ SandboxBroker::SetSecurityLevelForPlugin
                             sandbox::TargetPolicy::REG_ALLOW_ANY,
                             L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRULegacy\\*");
   SANDBOX_ENSURE_SUCCESS(result,
                          "With these static arguments AddRule should never fail, what happened?");
 
   return true;
 }
 
+#ifdef MOZ_ENABLE_SKIA_PDF
+bool
+SandboxBroker::SetSecurityLevelForPDFiumProcess()
+{
+  if (!mPolicy) {
+    return false;
+  }
+
+  auto result = SetJobLevel(mPolicy, sandbox::JOB_LOCKDOWN,
+                            0 /* ui_exceptions */);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "SetJobLevel should never fail with these arguments, what happened?");
+  result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+                                  sandbox::USER_LOCKDOWN);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "SetTokenLevel should never fail with these arguments, what happened?");
+
+  result = mPolicy->SetAlternateDesktop(true);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "Failed to create alternate desktop for sandbox.");
+
+  result = mPolicy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+  MOZ_ASSERT(sandbox::SBOX_ALL_OK == result,
+             "SetIntegrityLevel should never fail with these arguments, what happened?");
+
+  result =
+    mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "SetIntegrityLevel should never fail with these arguments, what happened?");
+
+  // XXX bug 1412933
+  // We should also disables win32k for the PDFium process by adding
+  // MITIGATION_WIN32K_DISABLE flag here after fixing bug 1412933.
+  sandbox::MitigationFlags mitigations =
+    sandbox::MITIGATION_BOTTOM_UP_ASLR |
+    sandbox::MITIGATION_HEAP_TERMINATE |
+    sandbox::MITIGATION_SEHOP |
+    sandbox::MITIGATION_DEP_NO_ATL_THUNK |
+    sandbox::MITIGATION_DEP |
+    sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
+    sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL;
+
+  if (!sRunningFromNetworkDrive) {
+    mitigations |= sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE;
+  }
+
+  result = mPolicy->SetProcessMitigations(mitigations);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "Invalid flags for SetProcessMitigations.");
+
+  mitigations =
+    sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
+    sandbox::MITIGATION_DLL_SEARCH_ORDER;
+
+  result = mPolicy->SetDelayedProcessMitigations(mitigations);
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "Invalid flags for SetDelayedProcessMitigations.");
+
+  // 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.*");
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "With these static arguments AddRule should never fail, what happened?");
+
+  // The PDFium process needs to be able to duplicate shared memory handles,
+  // which are Section handles, to the broker process.
+  result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
+                            sandbox::TargetPolicy::HANDLES_DUP_BROKER,
+                            L"Section");
+  MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
+                     "With these static arguments AddRule should never fail, hat happened?");
+
+  return true;
+}
+#endif
+
 bool
 SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
 {
   if (!mPolicy) {
     return false;
   }
 
   auto result = SetJobLevel(mPolicy, sandbox::JOB_LOCKDOWN,
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
@@ -43,16 +43,19 @@ public:
 #if defined(MOZ_CONTENT_SANDBOX)
   void SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
                                          bool aIsFileProcess);
 #endif
 
   void SetSecurityLevelForGPUProcess(int32_t aSandboxLevel);
 
   bool SetSecurityLevelForPluginProcess(int32_t aSandboxLevel);
+#ifdef MOZ_ENABLE_SKIA_PDF
+  bool SetSecurityLevelForPDFiumProcess();
+#endif
   enum SandboxLevel {
     LockDown,
     Restricted
   };
   bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel);
 
   // File system permissions
   bool AllowReadFile(wchar_t const *file);
--- a/widget/windows/PDFiumProcessChild.cpp
+++ b/widget/windows/PDFiumProcessChild.cpp
@@ -4,35 +4,57 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PDFiumProcessChild.h"
 
 #include "mozilla/ipc/IOThreadChild.h"
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
+#if defined(MOZ_SANDBOX)
+#include "mozilla/sandboxTarget.h"
+#endif
 
 using mozilla::ipc::IOThreadChild;
 
 namespace mozilla {
 namespace widget {
 
 PDFiumProcessChild::PDFiumProcessChild(ProcessId aParentPid)
   : ProcessChild(aParentPid)
+#if defined(MOZ_SANDBOX)
+  , mPDFium(nullptr)
+#endif
 {
 }
 
 PDFiumProcessChild::~PDFiumProcessChild()
 {
+#if defined(MOZ_SANDBOX)
+  if (mPDFium) {
+    PR_UnloadLibrary(mPDFium);
+  }
+#endif
 }
 
 bool
 PDFiumProcessChild::Init(int aArgc, char* aArgv[])
 {
   BackgroundHangMonitor::Startup();
+
+#if defined(MOZ_SANDBOX)
+  // XXX bug 1417000
+  // We really should load "pdfium.dll" after calling StartSandbox(). For
+  // an unknown reason, "pdfium.dll" can not be loaded correctly after
+  // StartSandbox() been called. Temporary preload this library until we fix
+  // bug 1417000.
+  mPDFium = PR_LoadLibrary("pdfium.dll");
+  mozilla::SandboxTarget::Instance()->StartSandbox();
+#endif
+
   mPDFiumActor.Init(ParentPid(),IOThreadChild::message_loop(),
                     IOThreadChild::channel());
 
   return true;
 }
 
 void
 PDFiumProcessChild::CleanUp()
--- a/widget/windows/PDFiumProcessChild.h
+++ b/widget/windows/PDFiumProcessChild.h
@@ -28,14 +28,17 @@ public:
   // ProcessChild functions.
   bool Init(int aArgc, char* aArgv[]) override;
   void CleanUp() override;
 
 private:
   DISALLOW_COPY_AND_ASSIGN(PDFiumProcessChild);
 
   PDFiumChild mPDFiumActor;
+#if defined(MOZ_SANDBOX)
+  PRLibrary*  mPDFium;
+#endif
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif // PDFIUMPROCESSCHILD_H_