Bug 1445003 - Detect RenderDoc and adjust the sandbox policy so it can work. r=gcp draft
authorJed Davis <jld@mozilla.com>
Mon, 12 Mar 2018 20:21:08 -0600
changeset 767532 d8a861af1ca25bb482a7abc7a19fa1c8cff86acc
parent 767347 80b4777a6421d8df4bb27ac23fb607c318a3006c
push id102627
push userbmo:jld@mozilla.com
push dateWed, 14 Mar 2018 19:19:57 +0000
reviewersgcp
bugs1445003
milestone61.0a1
Bug 1445003 - Detect RenderDoc and adjust the sandbox policy so it can work. r=gcp RenderDoc, a graphics debugging tool, uses a preload library that creates a listening socket (Internet-domain) early in startup and accepts connections from the frontend. If it's detected (via env vars), we allow accept/accept4 (but not socket/bind/listen), and remain in the parent process's network namespace so that other processes can connect to the socket. This doesn't change the sandbox policy if not running under RenderDoc. MozReview-Commit-ID: 964RW4BFh4u
security/sandbox/linux/SandboxFilter.cpp
security/sandbox/linux/launch/SandboxLaunch.cpp
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -374,16 +374,17 @@ public:
 // 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() : Move(aOrElse);
   }
   ResultExpr AllowBelowLevel(int aLevel) const {
@@ -739,16 +740,17 @@ private:
   }
 
 public:
   ContentSandboxPolicy(SandboxBrokerClient* aBroker,
                        ContentProcessSandboxParams&& aParams)
     : mBroker(aBroker)
     , mParams(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 {
     switch(aCall) {
     case SYS_RECVFROM:
     case SYS_SENDTO:
@@ -785,16 +787,22 @@ public:
     case SYS_SOCKET: {
       const auto trapFn = aHasArgs ? FakeSocketTrap : FakeSocketTrapLegacy;
       return Some(AllowBelowLevel(4, Trap(trapFn, nullptr)));
     }
     case SYS_CONNECT: {
       const auto trapFn = aHasArgs ? ConnectTrap : ConnectTrapLegacy;
       return Some(AllowBelowLevel(4, Trap(trapFn, mBroker)));
     }
+    case SYS_ACCEPT:
+    case SYS_ACCEPT4:
+      if (mUsingRenderDoc) {
+        return Some(Allow());
+      }
+      return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs);
     case SYS_RECV:
     case SYS_SEND:
     case SYS_GETSOCKOPT:
     case SYS_SETSOCKOPT:
     case SYS_GETSOCKNAME:
     case SYS_GETPEERNAME:
     case SYS_SHUTDOWN:
       return Some(Allow());
--- a/security/sandbox/linux/launch/SandboxLaunch.cpp
+++ b/security/sandbox/linux/launch/SandboxLaunch.cpp
@@ -272,18 +272,19 @@ SandboxLaunchPrepare(GeckoProcessType aT
 #endif
 #ifdef MOZ_CONTENT_SANDBOX
   case GeckoProcessType_Content:
     if (level >= 4) {
       canChroot = true;
       // Unshare network namespace if allowed by graphics; see
       // function definition above for details.  (The display
       // local-ness is cached because it won't change.)
-      static const bool isDisplayLocal = IsDisplayLocal();
-      if (isDisplayLocal) {
+      static const bool canCloneNet =
+        IsDisplayLocal() && !PR_GetEnv("RENDERDOC_CAPTUREOPTS");
+      if (canCloneNet) {
         flags |= CLONE_NEWNET;
       }
     }
     // Hidden pref to allow testing user namespaces separately, even
     // if there's nothing that would require them.
     if (Preferences::GetBool("security.sandbox.content.force-namespace", false)) {
       flags |= CLONE_NEWUSER;
     }