Backed out changeset 3a761e5cc19c (bug 1257361) for bustage
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 12 Dec 2016 11:49:35 +0100
changeset 352909 b54a7014e03d92571b341b9ce82772305685a58d
parent 352908 e84e0565f940ba97dc185179373ce123936ac432
child 352910 1e6736d8e0280252c2b584ebdf7becb8963e5821
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1257361
milestone52.0a2
backs out3a761e5cc19c38782cfc0da0bba68954bd06cd27
Backed out changeset 3a761e5cc19c (bug 1257361) for bustage
security/sandbox/linux/Sandbox.cpp
security/sandbox/linux/SandboxFilter.cpp
security/sandbox/linux/SandboxInternal.h
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -207,56 +207,51 @@ InstallSigSysHandler(void)
  * whitelist).
  *
  * PR_SET_NO_NEW_PRIVS ensures that it is impossible to grant more
  * syscalls to the process beyond this point (even after fork()), and
  * prevents gaining capabilities (e.g., by exec'ing a setuid root
  * program).  The kernel won't allow seccomp-bpf without doing this,
  * because otherwise it could be used for privilege escalation attacks.
  *
- * Returns false if the filter was already installed (see the
- * PR_SET_NO_NEW_PRIVS rule in SandboxFilter.cpp).  Crashes on any
- * other error condition.
+ * Returns false (and sets errno) on failure.
  *
  * @see SandboxInfo
  * @see BroadcastSetThreadSandbox
  */
 static bool MOZ_MUST_USE
 InstallSyscallFilter(const sock_fprog *aProg, bool aUseTSync)
 {
   if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-    if (!aUseTSync && errno == ETXTBSY) {
-      return false;
-    }
     SANDBOX_LOG_ERROR("prctl(PR_SET_NO_NEW_PRIVS) failed: %s", strerror(errno));
     MOZ_CRASH("prctl(PR_SET_NO_NEW_PRIVS)");
   }
 
   if (aUseTSync) {
     if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,
                 SECCOMP_FILTER_FLAG_TSYNC, aProg) != 0) {
       SANDBOX_LOG_ERROR("thread-synchronized seccomp failed: %s",
                         strerror(errno));
-      MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
+      return false;
     }
   } else {
     if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)aProg, 0, 0)) {
       SANDBOX_LOG_ERROR("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER) failed: %s",
                         strerror(errno));
-      MOZ_CRASH("seccomp+tsync failed, but kernel supports tsync");
+      return false;
     }
   }
   return true;
 }
 
 // Use signals for permissions that need to be set per-thread.
 // The communication channel from the signal handler back to the main thread.
 static mozilla::Atomic<int> gSetSandboxDone;
 // Pass the filter itself through a global.
-const sock_fprog* gSetSandboxFilter;
+static const sock_fprog* gSetSandboxFilter;
 
 // We have to dynamically allocate the signal number; see bug 1038900.
 // This function returns the first realtime signal currently set to
 // default handling (i.e., not in use), or 0 if none could be found.
 //
 // WARNING: if this function or anything similar to it (including in
 // external libraries) is used on multiple threads concurrently, there
 // will be a race condition.
@@ -275,17 +270,23 @@ FindFreeSignalNumber()
   return 0;
 }
 
 // Returns true if sandboxing was enabled, or false if sandboxing
 // already was enabled.  Crashes if sandboxing could not be enabled.
 static bool
 SetThreadSandbox()
 {
-  return InstallSyscallFilter(gSetSandboxFilter, false);
+  if (prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
+    if (!InstallSyscallFilter(gSetSandboxFilter, false)) {
+      MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
+    }
+    return true;
+  }
+  return false;
 }
 
 static void
 SetThreadSandboxHandler(int signum)
 {
   // The non-zero number sent back to the main thread indicates
   // whether action was taken.
   if (SetThreadSandbox()) {
@@ -445,17 +446,17 @@ static void
 ApplySandboxWithTSync(sock_fprog* aFilter)
 {
   EnterChroot();
   // At this point we're committed to using tsync, because the signal
   // broadcast workaround needs to access procfs.  (Unless chroot
   // isn't used... but this failure shouldn't happen in the first
   // place, so let's not make extra special cases for it.)
   if (!InstallSyscallFilter(aFilter, true)) {
-    MOZ_CRASH();
+    MOZ_CRASH("seccomp+tsync failed, but kernel supports tsync");
   }
 }
 
 // Common code for sandbox startup.
 static void
 SetCurrentProcessSandbox(UniquePtr<sandbox::bpf_dsl::Policy> aPolicy)
 {
   MOZ_ASSERT(gSandboxCrashFunc);
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -3,17 +3,16 @@
 /* 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 "SandboxFilter.h"
 #include "SandboxFilterUtil.h"
 
 #include "SandboxBrokerClient.h"
-#include "SandboxInfo.h"
 #include "SandboxInternal.h"
 #include "SandboxLogging.h"
 
 #include "mozilla/UniquePtr.h"
 
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ipc.h>
@@ -88,26 +87,16 @@ private:
   // bionic commit 10c8ce59a (in JB and up; API level 16 = Android 4.1).
   static intptr_t TKillCompatTrap(const sandbox::arch_seccomp_data& aArgs,
                                   void *aux)
   {
     return syscall(__NR_tgkill, getpid(), aArgs.args[0], aArgs.args[1]);
   }
 #endif
 
-  static intptr_t SetNoNewPrivsTrap(ArgsRef& aArgs, void* aux) {
-    if (gSetSandboxFilter == nullptr) {
-      // Called after BroadcastSetThreadSandbox finished, therefore
-      // not our doing and not expected.
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    // Signal that the filter is already in place.
-    return -ETXTBSY;
-  }
-
 public:
   virtual ResultExpr InvalidSyscall() const override {
     return Trap(BlockedSyscallTrap, nullptr);
   }
 
   virtual ResultExpr ClonePolicy(ResultExpr failPolicy) const {
     // Allow use for simple thread creation (pthread_create) only.
 
@@ -255,26 +244,18 @@ public:
       return Allow();
 #endif
 #ifdef ANDROID
     case __NR_set_tid_address:
       return Allow();
 #endif
 
       // prctl
-    case __NR_prctl: {
-      if (SandboxInfo::Get().Test(SandboxInfo::kHasSeccompTSync)) {
-        return PrctlPolicy();
-      }
-
-      Arg<int> option(0);
-      return If(option == PR_SET_NO_NEW_PRIVS,
-                Trap(SetNoNewPrivsTrap, nullptr))
-        .Else(PrctlPolicy());
-    }
+    case __NR_prctl:
+      return PrctlPolicy();
 
       // NSPR can call this when creating a thread, but it will accept a
       // polite "no".
     case __NR_getpriority:
       // But if thread creation races with sandbox startup, that call
       // could succeed, and then we get one of these:
     case __NR_setpriority:
       return Error(EACCES);
--- a/security/sandbox/linux/SandboxInternal.h
+++ b/security/sandbox/linux/SandboxInternal.h
@@ -6,23 +6,20 @@
 
 #ifndef mozilla_SandboxInternal_h
 #define mozilla_SandboxInternal_h
 
 #include <signal.h>
 
 #include "mozilla/Types.h"
 
-struct sock_fprog;
-
 namespace mozilla {
 
 // SandboxCrash() has to be in libxul to use internal interfaces, but
 // its caller in libmozsandbox.
 // See also bug 1101170.
 
 typedef void (*SandboxCrashFunc)(int, siginfo_t*, void*);
 extern MOZ_EXPORT SandboxCrashFunc gSandboxCrashFunc;
-extern const sock_fprog* gSetSandboxFilter;
 
 } // namespace mozilla
 
 #endif // mozilla_SandboxInternal_h