Bug 977859 - Drop uid 0 in all content processes immediately after fork. r=bent r=kang
authorJed Davis <jld@mozilla.com>
Wed, 12 Mar 2014 15:48:15 -0700
changeset 191565 602a61ed044801e993b1c5c5afed8473139906b3
parent 191564 acf4ff8446530c86c1aa7973accc4893f00596b5
child 191566 5708f8384619254008068e71d9384ae781155a26
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent, kang
bugs977859
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 977859 - Drop uid 0 in all content processes immediately after fork. r=bent r=kang Now all regular child processes, including preallocated, are deprivileged. Only Nuwa needs uid 0, because each of its children has a different uid/gid.
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
mozglue/build/Nuwa.cpp
security/sandbox/linux/Sandbox.cpp
security/sandbox/linux/Sandbox.h
toolkit/toolkit.mozbuild
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -27,22 +27,23 @@
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
 
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
+#if defined(MOZ_CONTENT_SANDBOX)
+#if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
+#elif defined(XP_LINUX)
+#include "mozilla/Sandbox.h"
 #endif
-#if defined(XP_LINUX)
-#include "mozilla/Sandbox.h"
 #endif
 
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
@@ -679,33 +680,26 @@ ContentChild::AllocPImageBridgeChild(moz
 PBackgroundChild*
 ContentChild::AllocPBackgroundChild(Transport* aTransport,
                                     ProcessId aOtherProcess)
 {
     return BackgroundChild::Alloc(aTransport, aOtherProcess);
 }
 
 bool
-ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
+ContentChild::RecvSetProcessSandbox()
 {
-  ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ?
-                          GeckoChildProcessHost::DefaultChildPrivileges() :
-                          aPrivs;
-#if defined(XP_LINUX)
-  // SetCurrentProcessSandbox includes SetCurrentProcessPrivileges.
-  // But we may want to move the sandbox initialization somewhere else
+  // We may want to move the sandbox initialization somewhere else
   // at some point; see bug 880808.
-  SetCurrentProcessSandbox(privs);
-#else
-  // If this fails, we die.
-  SetCurrentProcessPrivileges(privs);
+#if defined(MOZ_CONTENT_SANDBOX)
+#if defined(XP_LINUX)
+  SetCurrentProcessSandbox();
+#elif defined(XP_WIN)
+  mozilla::SandboxTarget::Instance()->StartSandbox();
 #endif
-
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
-  mozilla::SandboxTarget::Instance()->StartSandbox();
 #endif
   return true;
 }
 
 bool
 ContentChild::RecvSpeakerManagerNotify()
 {
 #ifdef MOZ_WIDGET_GONK
@@ -1850,11 +1844,18 @@ AddNewIPCProcess(pid_t aPid, NuwaProtoFd
 
 NS_EXPORT void
 OnNuwaProcessReady()
 {
     mozilla::dom::ContentChild* content =
         mozilla::dom::ContentChild::GetSingleton();
     content->SendNuwaReady();
 }
+
+NS_EXPORT void
+AfterNuwaFork()
+{
+    SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
+}
+
 #endif // MOZ_NUWA_PROCESS
 
 }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -81,17 +81,17 @@ public:
 
     PCompositorChild*
     AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
                           base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PImageBridgeChild*
     AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
                            base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
-    virtual bool RecvSetProcessPrivileges(const ChildPrivileges& aPrivs) MOZ_OVERRIDE;
+    virtual bool RecvSetProcessSandbox() MOZ_OVERRIDE;
 
     PBackgroundChild*
     AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
                           MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext &aContext,
                                               const uint32_t &chromeFlags);
     virtual bool DeallocPBrowserChild(PBrowserChild*);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -426,60 +426,53 @@ static const char* sObserverTopics[] = {
 /* static */ already_AddRefed<ContentParent>
 ContentParent::RunNuwaProcess()
 {
     MOZ_ASSERT(NS_IsMainThread());
     nsRefPtr<ContentParent> nuwaProcess =
         new ContentParent(/* aApp = */ nullptr,
                           /* aIsForBrowser = */ false,
                           /* aIsForPreallocated = */ true,
-                          // Final privileges are set when we
-                          // transform into our app.
-                          base::PRIVILEGES_INHERIT,
                           PROCESS_PRIORITY_BACKGROUND,
                           /* aIsNuwaProcess = */ true);
     nuwaProcess->Init();
     return nuwaProcess.forget();
 }
 
 // PreallocateAppProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within
 // MaybeTakePreallocatedAppProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateAppProcess()
 {
     nsRefPtr<ContentParent> process =
         new ContentParent(/* app = */ nullptr,
                           /* isForBrowserElement = */ false,
                           /* isForPreallocated = */ true,
-                          // Final privileges are set when we
-                          // transform into our app.
-                          base::PRIVILEGES_INHERIT,
                           PROCESS_PRIORITY_BACKGROUND);
     process->Init();
     return process.forget();
 }
 
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
-                                               ChildPrivileges aPrivs,
                                                ProcessPriority aInitialPriority)
 {
     nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
     if (!process) {
         return nullptr;
     }
 
-    if (!process->SetPriorityAndCheckIsAlive(aInitialPriority) ||
-        !process->TransformPreallocatedIntoApp(aAppManifestURL, aPrivs)) {
+    if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) {
         // Kill the process just in case it's not actually dead; we don't want
         // to "leak" this process!
         process->KillHard();
         return nullptr;
     }
+    process->TransformPreallocatedIntoApp(aAppManifestURL);
 
     return process.forget();
 }
 
 /*static*/ void
 ContentParent::StartUp()
 {
     if (XRE_GetProcessType() != GeckoProcessType_Default) {
@@ -575,17 +568,16 @@ ContentParent::GetNewOrUsed(bool aForBro
         NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sNonAppContentParents?");
         return p.forget();
     }
 
     nsRefPtr<ContentParent> p =
         new ContentParent(/* app = */ nullptr,
                           aForBrowserElement,
                           /* isForPreallocated = */ false,
-                          base::PRIVILEGES_DEFAULT,
                           PROCESS_PRIORITY_FOREGROUND);
     p->Init();
     sNonAppContentParents->AppendElement(p);
     return p.forget();
 }
 
 /*static*/ ProcessPriority
 ContentParent::GetInitialProcessPriority(Element* aFrameElement)
@@ -700,33 +692,31 @@ ContentParent::CreateBrowserOrApp(const 
         // Hopefully the process won't die after this point, if this call
         // succeeds.
         if (!p->SetPriorityAndCheckIsAlive(initialPriority)) {
             p = nullptr;
         }
     }
 
     if (!p) {
-        ChildPrivileges privs = base::PRIVILEGES_DEFAULT;
-        p = MaybeTakePreallocatedAppProcess(manifestURL, privs,
+        p = MaybeTakePreallocatedAppProcess(manifestURL,
                                             initialPriority);
         if (!p) {
 #ifdef MOZ_NUWA_PROCESS
             if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled",
                                      false)) {
                 // Returning nullptr from here so the frame loader will retry
                 // later when we have a spare process.
                 return nullptr;
             }
 #endif
             NS_WARNING("Unable to use pre-allocated app process");
             p = new ContentParent(ownApp,
                                   /* isForBrowserElement = */ false,
                                   /* isForPreallocated = */ false,
-                                  privs,
                                   initialPriority);
             p->Init();
         }
         sAppContentParents->Put(manifestURL, p);
     }
 
     uint32_t chromeFlags = 0;
 
@@ -956,25 +946,22 @@ TryGetNameFromManifestURL(const nsAStrin
 
     if (!app) {
         return;
     }
 
     app->GetName(aName);
 }
 
-bool
-ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL,
-                                            ChildPrivileges aPrivs)
+void
+ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL)
 {
     MOZ_ASSERT(IsPreallocated());
     mAppManifestURL = aAppManifestURL;
     TryGetNameFromManifestURL(aAppManifestURL, mAppName);
-
-    return SendSetProcessPrivileges(aPrivs);
 }
 
 void
 ContentParent::ShutDownProcess(bool aCloseWithError)
 {
     const InfallibleTArray<PIndexedDBParent*>& idbParents =
         ManagedPIndexedDBParent();
     for (uint32_t i = 0; i < idbParents.Length(); ++i) {
@@ -1338,21 +1325,19 @@ ContentParent::InitializeMembers()
     mCalledClose = false;
     mCalledCloseWithError = false;
     mCalledKillHard = false;
 }
 
 ContentParent::ContentParent(mozIApplication* aApp,
                              bool aIsForBrowser,
                              bool aIsForPreallocated,
-                             ChildPrivileges aOSPrivileges,
                              ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */,
                              bool aIsNuwaProcess /* = false */)
-    : mOSPrivileges(aOSPrivileges)
-    , mIsForBrowser(aIsForBrowser)
+    : mIsForBrowser(aIsForBrowser)
     , mIsNuwaProcess(aIsNuwaProcess)
 {
     InitializeMembers();  // Perform common initialization.
 
     // No more than one of !!aApp, aIsForBrowser, aIsForPreallocated should be
     // true.
     MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
 
@@ -1374,18 +1359,20 @@ ContentParent::ContentParent(mozIApplica
         mAppManifestURL = MAGIC_PREALLOCATED_APP_MANIFEST_URL;
     }
 
     // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
     // PID along with the warning.
     nsDebugImpl::SetMultiprocessMode("Parent");
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-    mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content,
-                                            aOSPrivileges);
+    ChildPrivileges privs = aIsNuwaProcess
+        ? base::PRIVILEGES_INHERIT
+        : base::PRIVILEGES_DEFAULT;
+    mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs);
     mSubprocess->SetSandboxEnabled(ShouldSandboxContentProcesses());
 
     IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
 
     if (!aIsNuwaProcess) {
         // Tell the memory reporter manager that this ContentParent exists.
         nsRefPtr<nsMemoryReporterManager> mgr =
             nsMemoryReporterManager::GetOrCreate();
@@ -1423,20 +1410,18 @@ FindFdProtocolFdMapping(const nsTArray<P
 /**
  * This constructor is used for new content process cloned from a template.
  *
  * For Nuwa.
  */
 ContentParent::ContentParent(ContentParent* aTemplate,
                              const nsAString& aAppManifestURL,
                              base::ProcessHandle aPid,
-                             const nsTArray<ProtocolFdMapping>& aFds,
-                             ChildPrivileges aOSPrivileges)
-    : mOSPrivileges(aOSPrivileges)
-    , mAppManifestURL(aAppManifestURL)
+                             const nsTArray<ProtocolFdMapping>& aFds)
+    : mAppManifestURL(aAppManifestURL)
     , mIsForBrowser(false)
     , mIsNuwaProcess(false)
 {
     InitializeMembers();  // Perform common initialization.
 
     sContentParents->insertBack(this);
 
     // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
@@ -1445,18 +1430,17 @@ ContentParent::ContentParent(ContentPare
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
     const FileDescriptor* fd = FindFdProtocolFdMapping(aFds, GetProtocolId());
 
     NS_ASSERTION(fd != nullptr, "IPC Channel for PContent is necessary!");
     mSubprocess = new GeckoExistingProcessHost(GeckoProcessType_Content,
                                                aPid,
-                                               *fd,
-                                               aOSPrivileges);
+                                               *fd);
 
     // Tell the memory reporter manager that this ContentParent exists.
     nsRefPtr<nsMemoryReporterManager> mgr =
         nsMemoryReporterManager::GetOrCreate();
     if (mgr) {
         mgr->IncrementNumChildProcesses();
     }
 
@@ -1590,26 +1574,24 @@ ContentParent::InitInternal(ProcessPrior
         for (uint32_t i = 0; i < authorSheets.Length(); i++) {
             URIParams uri;
             SerializeURI(authorSheets[i]->GetSheetURI(), uri);
             unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
         }
     }
 
 #ifdef MOZ_CONTENT_SANDBOX
-    // Bug 921817.  We enable the sandbox in RecvSetProcessPrivileges,
-    // which is where a preallocated process drops unnecessary privileges,
-    // but a non-preallocated process will already have changed its
-    // uid/gid/etc immediately after forking.  Thus, we send this message,
-    // which is otherwise a no-op, to sandbox it at an appropriate point
-    // during startup.
-    if (mOSPrivileges != base::PRIVILEGES_INHERIT) {
-        if (!SendSetProcessPrivileges(base::PRIVILEGES_INHERIT)) {
-            KillHard();
-        }
+    bool shouldSandbox = true;
+#ifdef MOZ_NUWA_PROCESS
+    if (IsNuwaProcess()) {
+        shouldSandbox = false;
+    }
+#endif
+    if (shouldSandbox && !SendSetProcessSandbox()) {
+        KillHard();
     }
 #endif
 }
 
 bool
 ContentParent::IsAlive()
 {
     return mIsAlive;
@@ -1961,18 +1943,17 @@ ContentParent::RecvAddNewProcess(const u
                       "AddNewProcess(%d)", Pid(), aPid);
         KillHard();
         return false;
     }
     nsRefPtr<ContentParent> content;
     content = new ContentParent(this,
                                 MAGIC_PREALLOCATED_APP_MANIFEST_URL,
                                 aPid,
-                                aFds,
-                                base::PRIVILEGES_INHERIT);
+                                aFds);
     content->Init();
     PreallocatedProcessManager::PublishSpareProcess(content);
     return true;
 #else
     NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
     return false;
 #endif
 }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -239,41 +239,38 @@ private:
     static void JoinProcessesIOThread(const nsTArray<ContentParent*>* aProcesses,
                                       Monitor* aMonitor, bool* aDone);
 
     // Take the preallocated process and transform it into a "real" app process,
     // for the specified manifest URL.  If there is no preallocated process (or
     // if it's dead), this returns false.
     static already_AddRefed<ContentParent>
     MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
-                                    ChildPrivileges aPrivs,
                                     hal::ProcessPriority aInitialPriority);
 
     static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
 
     // Hide the raw constructor methods since we don't want client code
     // using them.
     using PContentParent::SendPBrowserConstructor;
     using PContentParent::SendPTestShellConstructor;
 
     // No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
     // true.
     ContentParent(mozIApplication* aApp,
                   bool aIsForBrowser,
                   bool aIsForPreallocated,
-                  ChildPrivileges aOSPrivileges = base::PRIVILEGES_DEFAULT,
                   hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND,
                   bool aIsNuwaProcess = false);
 
 #ifdef MOZ_NUWA_PROCESS
     ContentParent(ContentParent* aTemplate,
                   const nsAString& aAppManifestURL,
                   base::ProcessHandle aPid,
-                  const nsTArray<ProtocolFdMapping>& aFds,
-                  ChildPrivileges aOSPrivileges = base::PRIVILEGES_DEFAULT);
+                  const nsTArray<ProtocolFdMapping>& aFds);
 #endif
 
     // The common initialization for the constructors.
     void InitializeMembers();
 
     // The common initialization logic shared by all constuctors.
     void InitInternal(ProcessPriority aPriority,
                       bool aSetupOffMainThreadCompositing,
@@ -291,20 +288,18 @@ private:
 
     // Set the child process's priority and then check whether the child is
     // still alive.  Returns true if the process is still alive, and false
     // otherwise.  If you pass a FOREGROUND* priority here, it's (hopefully)
     // unlikely that the process will be killed after this point.
     bool SetPriorityAndCheckIsAlive(hal::ProcessPriority aPriority);
 
     // Transform a pre-allocated app process into a "real" app
-    // process, for the specified manifest URL.  If this returns false, the
-    // child process has died.
-    bool TransformPreallocatedIntoApp(const nsAString& aAppManifestURL,
-                                      ChildPrivileges aPrivs);
+    // process, for the specified manifest URL.
+    void TransformPreallocatedIntoApp(const nsAString& aAppManifestURL);
 
     /**
      * Mark this ContentParent as dead for the purposes of Get*().
      * This method is idempotent.
      */
     void MarkAsDead();
 
     /**
@@ -534,17 +529,16 @@ private:
     virtual bool
     RecvBackUpXResources(const FileDescriptor& aXSocketFd) MOZ_OVERRIDE;
 
     // If you add strong pointers to cycle collected objects here, be sure to
     // release these objects in ShutDownProcess.  See the comment there for more
     // details.
 
     GeckoChildProcessHost* mSubprocess;
-    base::ChildPrivileges mOSPrivileges;
 
     uint64_t mChildID;
     int32_t mGeolocationWatchID;
 
     nsString mAppManifestURL;
 
     /**
      * We cache mAppName instead of looking it up using mAppManifestURL when we
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -262,21 +262,21 @@ both:
     async PBrowser(IPCTabContext context, uint32_t chromeFlags);
 
     async PBlob(BlobConstructorParams params);
 
     async PJavaScript();
 
 child:
     /**
-     * Update OS process privileges to |privs|.  Can usually only be
-     * performed zero or one times.  The child will abnormally exit if
-     * the privilege update fails.
+     * Enable system-level sandboxing features, if available.  Can
+     * usually only be performed zero or one times.  The child may
+     * abnormally exit if this fails; the details are OS-specific.
      */
-    async SetProcessPrivileges(ChildPrivileges privs);
+    async SetProcessSandbox();
 
     PMemoryReportRequest(uint32_t generation, bool minimizeMemoryUsage, nsString DMDDumpIdent);
 
     /**
      * Notify the AudioChannelService in the child processes.
      */
     async AudioChannelNotify();
 
--- a/mozglue/build/Nuwa.cpp
+++ b/mozglue/build/Nuwa.cpp
@@ -1530,16 +1530,27 @@ CloseAllProtoSockets(NuwaProtoFdInfo *aI
   int i;
 
   for (i = 0; i < aInfoSize; i++) {
     REAL(close)(aInfoList[i].newFds[0]);
     REAL(close)(aInfoList[i].newFds[1]);
   }
 }
 
+static void
+AfterForkHook()
+{
+  void (*AfterNuwaFork)();
+
+  // This is defined in dom/ipc/ContentChild.cpp
+  AfterNuwaFork = (void (*)())
+    dlsym(RTLD_DEFAULT, "AfterNuwaFork");
+  AfterNuwaFork();
+}
+
 /**
  * Fork a new process that is ready for running IPC.
  *
  * @return the PID of the new process.
  */
 static int
 ForkIPCProcess() {
   int pid;
@@ -1560,16 +1571,17 @@ ForkIPCProcess() {
     AddNewProcess(pid, sProtoFdInfos, sProtoFdInfosSize);
     CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize);
   } else {
     // in the child
     if (getenv("MOZ_DEBUG_CHILD_PROCESS")) {
       printf("\n\nNUWA CHILDCHILDCHILDCHILD\n  debug me @ %d\n\n", getpid());
       sleep(30);
     }
+    AfterForkHook();
     ReplaceSignalFds();
     ReplaceIPC(sProtoFdInfos, sProtoFdInfosSize);
     RecreateEpollFds();
     RecreateThreads();
     CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize);
   }
 
   sForkWaitCondChanged = true;
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -52,18 +52,16 @@ namespace mozilla {
 #define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
 #elif defined(PR_LOGGING)
 static PRLogModuleInfo* gSeccompSandboxLog;
 #define LOG_ERROR(args...) PR_LOG(gSeccompSandboxLog, PR_LOG_ERROR, (args))
 #else
 #define LOG_ERROR(args...)
 #endif
 
-// Note: this ifdef includes most of the file.
-#ifdef MOZ_CONTENT_SANDBOX
 struct sock_filter seccomp_filter[] = {
   VALIDATE_ARCHITECTURE,
   EXAMINE_SYSCALL,
   SECCOMP_WHITELIST,
 #ifdef MOZ_CONTENT_SANDBOX_REPORTER
   TRAP_PROCESS,
 #else
   KILL_PROCESS,
@@ -237,78 +235,61 @@ InstallSyscallFilter(void)
     return 1;
   }
 
   if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &seccomp_prog, 0, 0)) {
     return 1;
   }
   return 0;
 }
-#endif
 
-#if defined(ANDROID) || defined(MOZ_CONTENT_SANDBOX)
 // Use signals for permissions that need to be set per-thread.
-static base::ChildPrivileges sSetPrivilegesTo;
 // The communication channel from the signal handler back to the main thread.
 static mozilla::Atomic<int> sSetSandboxDone;
 // about:memory has the first 3 RT signals.  (We should allocate
 // signals centrally instead of hard-coding them like this.)
 static const int sSetSandboxSignum = SIGRTMIN + 3;
-#endif
 
 static bool
-SetThreadSandbox(base::ChildPrivileges aPrivs, bool aIsMainThread)
+SetThreadSandbox()
 {
   bool didAnything = false;
-  bool shouldSetPrivs = aIsMainThread;
-#if defined(ANDROID)
-  shouldSetPrivs = true;
-#endif
 
-  if (shouldSetPrivs && (aIsMainThread || geteuid() == 0)) {
-    SetCurrentProcessPrivileges(aPrivs);
-    if (aPrivs != base::PRIVILEGES_INHERIT) {
-      didAnything = true;
-    }
-  }
-#if defined(MOZ_CONTENT_SANDBOX)
   if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
       prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
     if (InstallSyscallFilter() == 0) {
       didAnything = true;
     }
     /*
      * Bug 880797: when all B2G devices are required to support
      * seccomp-bpf, this should exit/crash if InstallSyscallFilter
      * returns nonzero (ifdef MOZ_WIDGET_GONK).
      */
   }
-#endif
   return didAnything;
 }
 
-#if defined(ANDROID) || defined(MOZ_CONTENT_SANDBOX)
 static void
 SetThreadSandboxHandler(int signum)
 {
   // The non-zero number sent back to the main thread indicates
   // whether action was taken.
-  if (SetThreadSandbox(sSetPrivilegesTo, /* main: */ false)) {
+  if (SetThreadSandbox()) {
     sSetSandboxDone = 2;
   } else {
     sSetSandboxDone = 1;
   }
   // Wake up the main thread.  See the FUTEX_WAIT call, below, for an
   // explanation.
   syscall(__NR_futex, reinterpret_cast<int*>(&sSetSandboxDone),
           FUTEX_WAKE, 1);
 }
 
 static void
-BroadcastSetThreadSandbox(base::ChildPrivileges aPrivs)
+BroadcastSetThreadSandbox()
 {
   pid_t pid, tid;
   DIR *taskdp;
   struct dirent *de;
 
   static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
                 "mozilla::Atomic<int> isn't represented by an int");
   MOZ_ASSERT(NS_IsMainThread());
@@ -321,17 +302,16 @@ BroadcastSetThreadSandbox(base::ChildPri
   if (signal(sSetSandboxSignum, SetThreadSandboxHandler) != SIG_DFL) {
     LOG_ERROR("signal %d in use!\n", sSetSandboxSignum);
     MOZ_CRASH();
   }
 
   // In case this races with a not-yet-deprivileged thread cloning
   // itself, repeat iterating over all threads until we find none
   // that are still privileged.
-  sSetPrivilegesTo = aPrivs;
   bool sandboxProgress;
   do {
     sandboxProgress = false;
     // For each thread...
     while ((de = readdir(taskdp))) {
       char *endptr;
       tid = strtol(de->d_name, &endptr, 10);
       if (*endptr != '\0' || tid <= 0) {
@@ -412,46 +392,38 @@ BroadcastSetThreadSandbox(base::ChildPri
         }
       }
     }
     rewinddir(taskdp);
   } while (sandboxProgress);
   unused << signal(sSetSandboxSignum, SIG_DFL);
   unused << closedir(taskdp);
   // And now, deprivilege the main thread:
-  SetThreadSandbox(aPrivs, /* main: */ true);
+  SetThreadSandbox();
 }
-#else
-static void
-BroadcastSetThreadSandbox(base::ChildPrivileges aPrivs)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  SetThreadSandbox(aPrivs, /* main: */ true);
-}
-#endif
 
 /**
  * Starts the seccomp sandbox for this process and sets user/group-based privileges.
  * Should be called only once, and before any potentially harmful content is loaded.
  *
  * Should normally make the process exit on failure.
 */
 void
-SetCurrentProcessSandbox(base::ChildPrivileges aPrivs)
+SetCurrentProcessSandbox()
 {
 #if !defined(ANDROID) && defined(PR_LOGGING)
   if (!gSeccompSandboxLog) {
     gSeccompSandboxLog = PR_NewLogModule("SeccompSandbox");
   }
   PR_ASSERT(gSeccompSandboxLog);
 #endif
 
-#if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_CONTENT_SANDBOX_REPORTER)
+#if defined(MOZ_CONTENT_SANDBOX_REPORTER)
   if (InstallSyscallReporter()) {
     LOG_ERROR("install_syscall_reporter() failed\n");
   }
 #endif
 
-  BroadcastSetThreadSandbox(aPrivs);
+  BroadcastSetThreadSandbox();
 }
 
 } // namespace mozilla
 
--- a/security/sandbox/linux/Sandbox.h
+++ b/security/sandbox/linux/Sandbox.h
@@ -2,18 +2,16 @@
 /* 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 mozilla_Sandbox_h
 #define mozilla_Sandbox_h
 
-#include "base/process_util.h"
-
 namespace mozilla {
 
-void SetCurrentProcessSandbox(base::ChildPrivileges aPrivs);
+void SetCurrentProcessSandbox();
 
 } // namespace mozilla
 
 #endif // mozilla_Sandbox_h
 
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -1,17 +1,17 @@
 # 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/.
 
 if CONFIG['LIBXUL_SDK']:
     error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=')
 
-if CONFIG['MOZ_CONTENT_SANDBOX'] or CONFIG['OS_ARCH'] == 'Linux':
+if CONFIG['MOZ_CONTENT_SANDBOX']:
     add_tier_dir('sandbox', 'security/sandbox')
 
 # Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
 # builds fail.
 add_tier_dir('platform', 'security/certverifier')
 
 # Depends on certverifier
 add_tier_dir('platform', 'security/apps')