Bug 1511560 - Move the Linux sandbox broker hooks into SandboxPolicyCommon. r=gcp
authorJed Davis <jld@mozilla.com>
Sat, 23 Feb 2019 00:44:06 +0000
changeset 519400 48431f63d84227177951f65c9c828548d9a8bbb2
parent 519399 56f39977c72c62e0fdff0e5f68e72d6091b221db
child 519401 bab79f85596242146787d6d2a5ad56596cc1343e
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgcp
bugs1511560
milestone67.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 1511560 - Move the Linux sandbox broker hooks into SandboxPolicyCommon. r=gcp This will allow other policies to use brokering if needed (e.g., RDD and similar utility processes may need to access /dev/shm to create shared memory). The concrete policy class can deny filesystem access completely (matching the current behavior of the GMP policy) by passing nullptr to the superclass constructor instead. Depends on D14520 Differential Revision: https://phabricator.services.mozilla.com/D14521
security/sandbox/linux/SandboxFilter.cpp
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -85,20 +85,27 @@ using namespace sandbox::bpf_dsl;
 // normally interpreted: returning -ENOSYS from a Trap() handler
 // indicates an unexpected system call; SigSysHandler() in Sandbox.cpp
 // will detect this, request a crash dump, and terminate the process.
 // This does not apply to using Error(ENOSYS) in the policy, so that
 // can be used if returning an actual ENOSYS is needed.
 
 namespace mozilla {
 
-// This class whitelists everything used by the sandbox itself, by the
-// core IPC code, by the crash reporter, or other core code.
+// This class allows everything used by the sandbox itself, by the
+// core IPC code, by the crash reporter, or other core code.  It also
+// contains support for brokering file operations, but file access is
+// denied if no broker client is provided by the concrete class.
 class SandboxPolicyCommon : public SandboxPolicyBase {
  protected:
+  SandboxBrokerClient* mBroker;
+
+  explicit SandboxPolicyCommon(SandboxBrokerClient* aBroker = nullptr)
+      : mBroker(aBroker) {}
+
   typedef const sandbox::arch_seccomp_data& ArgsRef;
 
   static intptr_t BlockedSyscallTrap(ArgsRef aArgs, void* aux) {
     MOZ_ASSERT(!aux);
     return -ENOSYS;
   }
 
   // Convert Unix-style "return -1 and set errno" APIs back into the
@@ -127,16 +134,169 @@ class SandboxPolicyCommon : public Sandb
       // 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;
   }
 
+  // Trap handlers for filesystem brokering.
+  // (The amount of code duplication here could be improved....)
+#ifdef __NR_open
+  static intptr_t OpenTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto flags = static_cast<int>(aArgs.args[1]);
+    return broker->Open(path, flags);
+  }
+#endif
+
+  static intptr_t OpenAtTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto fd = static_cast<int>(aArgs.args[0]);
+    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
+    auto flags = static_cast<int>(aArgs.args[2]);
+    if (fd != AT_FDCWD && path[0] != '/') {
+      SANDBOX_LOG_ERROR("unsupported fd-relative openat(%d, \"%s\", 0%o)", fd,
+                        path, flags);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    return broker->Open(path, flags);
+  }
+
+#ifdef __NR_access
+  static intptr_t AccessTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto mode = static_cast<int>(aArgs.args[1]);
+    return broker->Access(path, mode);
+  }
+#endif
+
+  static intptr_t AccessAtTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto fd = static_cast<int>(aArgs.args[0]);
+    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
+    auto mode = static_cast<int>(aArgs.args[2]);
+    // Linux's faccessat syscall has no "flags" argument.  Attempting
+    // to handle the flags != 0 case is left to userspace; this is
+    // impossible to do correctly in all cases, but that's not our
+    // problem.
+    if (fd != AT_FDCWD && path[0] != '/') {
+      SANDBOX_LOG_ERROR("unsupported fd-relative faccessat(%d, \"%s\", %d)", fd,
+                        path, mode);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    return broker->Access(path, mode);
+  }
+
+  static intptr_t StatTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
+    return broker->Stat(path, buf);
+  }
+
+  static intptr_t LStatTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
+    return broker->LStat(path, buf);
+  }
+
+  static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto fd = static_cast<int>(aArgs.args[0]);
+    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
+    auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
+    auto flags = static_cast<int>(aArgs.args[3]);
+    if (fd != AT_FDCWD && path[0] != '/') {
+      SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
+                        fd, path, buf, flags);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
+      SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
+                        (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    return (flags & AT_SYMLINK_NOFOLLOW) == 0 ? broker->Stat(path, buf)
+                                              : broker->LStat(path, buf);
+  }
+
+  static intptr_t ChmodTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto mode = static_cast<mode_t>(aArgs.args[1]);
+    return broker->Chmod(path, mode);
+  }
+
+  static intptr_t LinkTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
+    return broker->Link(path, path2);
+  }
+
+  static intptr_t SymlinkTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
+    return broker->Symlink(path, path2);
+  }
+
+  static intptr_t RenameTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
+    return broker->Rename(path, path2);
+  }
+
+  static intptr_t MkdirTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto mode = static_cast<mode_t>(aArgs.args[1]);
+    return broker->Mkdir(path, mode);
+  }
+
+  static intptr_t RmdirTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    return broker->Rmdir(path);
+  }
+
+  static intptr_t UnlinkTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    return broker->Unlink(path);
+  }
+
+  static intptr_t ReadlinkTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    auto buf = reinterpret_cast<char*>(aArgs.args[1]);
+    auto size = static_cast<size_t>(aArgs.args[2]);
+    return broker->Readlink(path, buf, size);
+  }
+
+  static intptr_t ReadlinkAtTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto fd = static_cast<int>(aArgs.args[0]);
+    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
+    auto buf = reinterpret_cast<char*>(aArgs.args[2]);
+    auto size = static_cast<size_t>(aArgs.args[3]);
+    if (fd != AT_FDCWD && path[0] != '/') {
+      SANDBOX_LOG_ERROR("unsupported fd-relative readlinkat(%d, %s, %p, %u)",
+                        fd, path, buf, size);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    return broker->Readlink(path, buf, size);
+  }
+
  public:
   ResultExpr InvalidSyscall() const override {
     return Trap(BlockedSyscallTrap, nullptr);
   }
 
   virtual ResultExpr ClonePolicy(ResultExpr failPolicy) const {
     // Allow use for simple thread creation (pthread_create) only.
 
@@ -182,16 +342,56 @@ class SandboxPolicyCommon : public Sandb
       case SYS_SENDMSG:
         return Some(Allow());
       default:
         return Nothing();
     }
   }
 
   ResultExpr EvaluateSyscall(int sysno) const override {
+    // If a file broker client was provided, route syscalls to it;
+    // otherwise, fall through to the main policy, which will deny
+    // them.
+    if (mBroker != nullptr) {
+      switch (sysno) {
+        case __NR_open:
+          return Trap(OpenTrap, mBroker);
+        case __NR_openat:
+          return Trap(OpenAtTrap, mBroker);
+        case __NR_access:
+          return Trap(AccessTrap, mBroker);
+        case __NR_faccessat:
+          return Trap(AccessAtTrap, mBroker);
+        CASES_FOR_stat:
+          return Trap(StatTrap, mBroker);
+        CASES_FOR_lstat:
+          return Trap(LStatTrap, mBroker);
+        CASES_FOR_fstatat:
+          return Trap(StatAtTrap, mBroker);
+        case __NR_chmod:
+          return Trap(ChmodTrap, mBroker);
+        case __NR_link:
+          return Trap(LinkTrap, mBroker);
+        case __NR_mkdir:
+          return Trap(MkdirTrap, mBroker);
+        case __NR_symlink:
+          return Trap(SymlinkTrap, mBroker);
+        case __NR_rename:
+          return Trap(RenameTrap, mBroker);
+        case __NR_rmdir:
+          return Trap(RmdirTrap, mBroker);
+        case __NR_unlink:
+          return Trap(UnlinkTrap, mBroker);
+        case __NR_readlink:
+          return Trap(ReadlinkTrap, mBroker);
+        case __NR_readlinkat:
+          return Trap(ReadlinkAtTrap, mBroker);
+      }
+    }
+
     switch (sysno) {
         // Timekeeping
       case __NR_clock_gettime: {
         Arg<clockid_t> clk_id(0);
         return If(clk_id == CLOCK_MONOTONIC, Allow())
 #ifdef CLOCK_MONOTONIC_COARSE
             // Used by SandboxReporter, among other things.
             .ElseIf(clk_id == CLOCK_MONOTONIC_COARSE, Allow())
@@ -367,17 +567,16 @@ class SandboxPolicyCommon : public Sandb
 #ifdef MOZ_CONTENT_SANDBOX
 // The seccomp-bpf filter for content processes is not a true sandbox
 // on its own; its purpose is attack surface reduction and syscall
 // interception in support of a semantic sandboxing layer.  On B2G
 // this is the Android process permission model; on desktop,
 // namespaces and chroot() will be used.
 class ContentSandboxPolicy : public SandboxPolicyCommon {
  private:
-  SandboxBrokerClient* mBroker;
   ContentProcessSandboxParams mParams;
   bool mAllowSysV;
   bool mUsingRenderDoc;
 
   bool BelowLevel(int aLevel) const { return mParams.mLevel < aLevel; }
   ResultExpr AllowBelowLevel(int aLevel, ResultExpr aOrElse) const {
     return BelowLevel(aLevel) ? Allow() : std::move(aOrElse);
   }
@@ -399,169 +598,16 @@ class ContentSandboxPolicy : public Sand
     close(fd);
 #    endif  // __NR_socketcall
     return true;
 #  else   // ifndef __NR_socket
     return false;
 #  endif  // __NR_socket
   }
 
-  // Trap handlers for filesystem brokering.
-  // (The amount of code duplication here could be improved....)
-#  ifdef __NR_open
-  static intptr_t OpenTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto flags = static_cast<int>(aArgs.args[1]);
-    return broker->Open(path, flags);
-  }
-#  endif
-
-  static intptr_t OpenAtTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto fd = static_cast<int>(aArgs.args[0]);
-    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
-    auto flags = static_cast<int>(aArgs.args[2]);
-    if (fd != AT_FDCWD && path[0] != '/') {
-      SANDBOX_LOG_ERROR("unsupported fd-relative openat(%d, \"%s\", 0%o)", fd,
-                        path, flags);
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    return broker->Open(path, flags);
-  }
-
-#  ifdef __NR_access
-  static intptr_t AccessTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto mode = static_cast<int>(aArgs.args[1]);
-    return broker->Access(path, mode);
-  }
-#  endif
-
-  static intptr_t AccessAtTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto fd = static_cast<int>(aArgs.args[0]);
-    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
-    auto mode = static_cast<int>(aArgs.args[2]);
-    // Linux's faccessat syscall has no "flags" argument.  Attempting
-    // to handle the flags != 0 case is left to userspace; this is
-    // impossible to do correctly in all cases, but that's not our
-    // problem.
-    if (fd != AT_FDCWD && path[0] != '/') {
-      SANDBOX_LOG_ERROR("unsupported fd-relative faccessat(%d, \"%s\", %d)", fd,
-                        path, mode);
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    return broker->Access(path, mode);
-  }
-
-  static intptr_t StatTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
-    return broker->Stat(path, buf);
-  }
-
-  static intptr_t LStatTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
-    return broker->LStat(path, buf);
-  }
-
-  static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto fd = static_cast<int>(aArgs.args[0]);
-    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
-    auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
-    auto flags = static_cast<int>(aArgs.args[3]);
-    if (fd != AT_FDCWD && path[0] != '/') {
-      SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
-                        fd, path, buf, flags);
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
-      SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
-                        (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags);
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    return (flags & AT_SYMLINK_NOFOLLOW) == 0 ? broker->Stat(path, buf)
-                                              : broker->LStat(path, buf);
-  }
-
-  static intptr_t ChmodTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto mode = static_cast<mode_t>(aArgs.args[1]);
-    return broker->Chmod(path, mode);
-  }
-
-  static intptr_t LinkTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
-    return broker->Link(path, path2);
-  }
-
-  static intptr_t SymlinkTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
-    return broker->Symlink(path, path2);
-  }
-
-  static intptr_t RenameTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
-    return broker->Rename(path, path2);
-  }
-
-  static intptr_t MkdirTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto mode = static_cast<mode_t>(aArgs.args[1]);
-    return broker->Mkdir(path, mode);
-  }
-
-  static intptr_t RmdirTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    return broker->Rmdir(path);
-  }
-
-  static intptr_t UnlinkTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    return broker->Unlink(path);
-  }
-
-  static intptr_t ReadlinkTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
-    auto buf = reinterpret_cast<char*>(aArgs.args[1]);
-    auto size = static_cast<size_t>(aArgs.args[2]);
-    return broker->Readlink(path, buf, size);
-  }
-
-  static intptr_t ReadlinkAtTrap(ArgsRef aArgs, void* aux) {
-    auto broker = static_cast<SandboxBrokerClient*>(aux);
-    auto fd = static_cast<int>(aArgs.args[0]);
-    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
-    auto buf = reinterpret_cast<char*>(aArgs.args[2]);
-    auto size = static_cast<size_t>(aArgs.args[3]);
-    if (fd != AT_FDCWD && path[0] != '/') {
-      SANDBOX_LOG_ERROR("unsupported fd-relative readlinkat(%d, %s, %p, %u)",
-                        fd, path, buf, size);
-      return BlockedSyscallTrap(aArgs, nullptr);
-    }
-    return broker->Readlink(path, buf, size);
-  }
-
   static intptr_t GetPPidTrap(ArgsRef aArgs, void* aux) {
     // In a pid namespace, getppid() will return 0. We will return 0 instead
     // of the real parent pid to see what breaks when we introduce the
     // pid namespace (Bug 1151624).
     return 0;
   }
 
   static intptr_t SocketpairDatagramTrap(ArgsRef aArgs, void* aux) {
@@ -728,17 +774,17 @@ class ContentSandboxPolicy : public Sand
                              static_cast<int>(innerArgs[0]),
                              reinterpret_cast<AddrPtr>(innerArgs[1]),
                              static_cast<socklen_t>(innerArgs[2]));
   }
 
  public:
   ContentSandboxPolicy(SandboxBrokerClient* aBroker,
                        ContentProcessSandboxParams&& aParams)
-      : mBroker(aBroker),
+      : SandboxPolicyCommon(aBroker),
         mParams(std::move(aParams)),
         mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr),
         mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) {}
 
   ~ContentSandboxPolicy() override = default;
 
   Maybe<ResultExpr> EvaluateSocketCall(int aCall,
                                        bool aHasArgs) const override {
@@ -850,57 +896,20 @@ class ContentSandboxPolicy : public Sand
         whitelist.end()) {
       if (SandboxInfo::Get().Test(SandboxInfo::kVerbose)) {
         SANDBOX_LOG_ERROR("Allowing syscall nr %d via whitelist", sysno);
       }
       return Allow();
     }
 
     // Level 1 allows direct filesystem access; higher levels use
-    // brokering.
-    if (!BelowLevel(2)) {
-      // Have broker; route the appropriate syscalls to it.
-      MOZ_RELEASE_ASSERT(mBroker != nullptr);
-      switch (sysno) {
-        case __NR_open:
-          return Trap(OpenTrap, mBroker);
-        case __NR_openat:
-          return Trap(OpenAtTrap, mBroker);
-        case __NR_access:
-          return Trap(AccessTrap, mBroker);
-        case __NR_faccessat:
-          return Trap(AccessAtTrap, mBroker);
-        CASES_FOR_stat:
-          return Trap(StatTrap, mBroker);
-        CASES_FOR_lstat:
-          return Trap(LStatTrap, mBroker);
-        CASES_FOR_fstatat:
-          return Trap(StatAtTrap, mBroker);
-        case __NR_chmod:
-          return Trap(ChmodTrap, mBroker);
-        case __NR_link:
-          return Trap(LinkTrap, mBroker);
-        case __NR_mkdir:
-          return Trap(MkdirTrap, mBroker);
-        case __NR_symlink:
-          return Trap(SymlinkTrap, mBroker);
-        case __NR_rename:
-          return Trap(RenameTrap, mBroker);
-        case __NR_rmdir:
-          return Trap(RmdirTrap, mBroker);
-        case __NR_unlink:
-          return Trap(UnlinkTrap, mBroker);
-        case __NR_readlink:
-          return Trap(ReadlinkTrap, mBroker);
-        case __NR_readlinkat:
-          return Trap(ReadlinkAtTrap, mBroker);
-      }
-    } else {
-      // No broker; allow the syscalls directly.  )-:
-      MOZ_ASSERT(!mBroker);
+    // brokering (by falling through to the main policy and delegating
+    // to SandboxPolicyCommon).
+    if (BelowLevel(2)) {
+      MOZ_ASSERT(mBroker == nullptr);
       switch (sysno) {
         case __NR_open:
         case __NR_openat:
         case __NR_access:
         case __NR_faccessat:
         CASES_FOR_stat:
         CASES_FOR_lstat:
         CASES_FOR_fstatat: