Bug 1386404 - Intercept access to /tmp and rewrite to content process tempdir. r?jld draft
authorGian-Carlo Pascutto <gcp@mozilla.com>
Thu, 26 Oct 2017 17:50:49 +0200
changeset 749379 33efd3bf5e4bfa849fcec9d158c0844387a45dc8
parent 749378 863c67d57e88142ae5202e729e3c0c41e179515b
child 749380 8f60c28b351faff34842ab0aa4dc0a6ff2604cab
push id97374
push usergpascutto@mozilla.com
push dateWed, 31 Jan 2018 09:19:12 +0000
reviewersjld
bugs1386404
milestone60.0a1
Bug 1386404 - Intercept access to /tmp and rewrite to content process tempdir. r?jld MozReview-Commit-ID: 2h9hw6opYof
ipc/glue/GeckoChildProcessHost.cpp
security/sandbox/linux/broker/SandboxBroker.cpp
security/sandbox/linux/broker/SandboxBroker.h
security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -515,20 +515,16 @@ GeckoChildProcessHost::PerformAsyncLaunc
   }
 
 #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
   if (!mTmpDirName.IsEmpty()) {
     // Point a bunch of things that might want to write from content to our
     // shiny new content-process specific tmpdir
     mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
       ENVIRONMENT_STRING(mTmpDirName);
-    mLaunchOptions->env_map[ENVIRONMENT_LITERAL("XDG_CACHE_HOME")] =
-      ENVIRONMENT_STRING(mTmpDirName);
-    mLaunchOptions->env_map[ENVIRONMENT_LITERAL("XDG_CACHE_DIR")] =
-      ENVIRONMENT_STRING(mTmpDirName);
     // Partial fix for bug 1380051 (not persistent - should be)
     mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
       ENVIRONMENT_STRING(mTmpDirName);
   }
 #endif
 
   return PerformAsyncLaunchInternal(aExtraOpts);
 }
--- a/security/sandbox/linux/broker/SandboxBroker.cpp
+++ b/security/sandbox/linux/broker/SandboxBroker.cpp
@@ -23,16 +23,19 @@
 
 #include "base/string_util.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Move.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/ipc/FileDescriptor.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "SpecialSystemDirectory.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 
 namespace mozilla {
 
 // This constructor signals failure by setting mFileDesc and aClientFd to -1.
 SandboxBroker::SandboxBroker(UniquePtr<const Policy> aPolicy, int aChildPid,
                              int& aClientFd)
   : mChildPid(aChildPid), mPolicy(Move(aPolicy))
@@ -510,16 +513,44 @@ SandboxBroker::ConvertToRealPath(char* a
       // Size changed, but guaranteed to be 0 terminated
       aPathLen = strlen(aPath);
     }
     // ValidatePath will handle failure to translate
   }
   return aPathLen;
 }
 
+size_t
+SandboxBroker::RemapTempDirs(char* aPath, size_t aBufSize, size_t aPathLen)
+{
+  nsAutoCString path(aPath);
+  static const nsLiteralCString tempPrefix(NS_LITERAL_CSTRING("/tmp"));
+
+  if (StringBeginsWith(path, tempPrefix)) {
+    size_t prefixLen = tempPrefix.Length();
+    const nsDependentCSubstring cutPath =
+      Substring(path, prefixLen, path.Length() - prefixLen);
+    // Only now try to get the content process temp dir
+    nsCOMPtr<nsIFile> tmpDir;
+    nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
+                                          getter_AddRefs(tmpDir));
+    if (NS_SUCCEEDED(rv)) {
+      nsAutoCString tmpPath;
+      rv = tmpDir->GetNativePath(tmpPath);
+      if (NS_SUCCEEDED(rv)) {
+        tmpPath.Append(cutPath);
+        base::strlcpy(aPath, tmpPath.get(), aBufSize);
+        return strlen(aPath);
+      }
+    }
+  }
+
+  return aPathLen;
+}
+
 nsCString
 SandboxBroker::ReverseSymlinks(const nsACString& aPath)
 {
   // Revert any symlinks we previously resolved.
   int32_t cutLength = aPath.Length();
   nsCString cutPath(Substring(aPath, 0, cutLength));
 
   for (;;) {
@@ -670,16 +701,17 @@ SandboxBroker::ThreadMain(void)
       // enforced below.
       strncpy(pathBuf2, recvBuf + first_len + 1, kMaxPathLen + 1);
 
       // First string is guaranteed to be 0-terminated.
       pathLen = first_len;
 
       // Look up the first pathname but first translate relative paths.
       pathLen = ConvertToRealPath(pathBuf, sizeof(pathBuf), pathLen);
+      pathLen = RemapTempDirs(pathBuf, sizeof(pathBuf), pathLen);
       perms = mPolicy->Lookup(nsDependentCString(pathBuf, pathLen));
 
       // We don't have read permissions on the requested dir.
       // Did we arrive from a symlink in a path that is not writable?
       // Then try to figure out the original path and see if that is readable.
       if (!(perms & MAY_READ)) {
           // Work on the original path,
           // this reverses ConvertToRealPath above.
--- a/security/sandbox/linux/broker/SandboxBroker.h
+++ b/security/sandbox/linux/broker/SandboxBroker.h
@@ -138,16 +138,18 @@ class SandboxBroker final
 
   SandboxBroker(UniquePtr<const Policy> aPolicy, int aChildPid,
                 int& aClientFd);
   void ThreadMain(void) override;
   void AuditPermissive(int aOp, int aFlags, int aPerms, const char* aPath);
   void AuditDenial(int aOp, int aFlags, int aPerms, const char* aPath);
   // Remap relative paths to absolute paths.
   size_t ConvertToRealPath(char* aPath, size_t aBufSize, size_t aPathLen);
+  // Remap references to /tmp and friends to the content process tempdir
+  size_t RemapTempDirs(char* aPath, size_t aBufSize, size_t aPathLen);
   nsCString ReverseSymlinks(const nsACString& aPath);
   // Retrieves permissions for the path the original symlink sits in.
   int SymlinkPermissions(const char* aPath, const size_t aPathLen);
   // In SandboxBrokerRealPath.cpp
   char* SymlinkPath(const Policy* aPolicy, const char* __restrict aPath,
                     char* __restrict aResolved, int* aPermission);
 
   // Holding a UniquePtr should disallow copying, but to make that explicit:
--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
@@ -228,18 +228,16 @@ SandboxBrokerPolicyFactory::SandboxBroke
   policy->AddDir(rdonly, "/usr/lib32");
   policy->AddDir(rdonly, "/usr/lib64");
   policy->AddDir(rdonly, "/etc");
 #ifdef MOZ_PULSEAUDIO
   policy->AddPath(rdonly, "/var/lib/dbus/machine-id");
 #endif
   policy->AddDir(rdonly, "/usr/share");
   policy->AddDir(rdonly, "/usr/local/share");
-  policy->AddDir(rdonly, "/usr/tmp");
-  policy->AddDir(rdonly, "/var/tmp");
   // Various places where fonts reside
   policy->AddDir(rdonly, "/usr/X11R6/lib/X11/fonts");
   policy->AddDir(rdonly, "/nix/store");
   policy->AddDir(rdonly, "/run/host/fonts");
   policy->AddDir(rdonly, "/run/host/user-fonts");
 
   AddMesaSysfsPaths(policy);
   AddLdconfigPaths(policy);