Bug 1384986 - Fix DConf breakage caused by read restrictions. r=gcp draft
authorJed Davis <jld@mozilla.com>
Thu, 27 Jul 2017 11:32:09 -0600
changeset 619379 37efeccca5f2a6d69774de7bbabdbb43876baa38
parent 619309 a3e675a3b10a0ea289c301bedc31866f3daf7875
child 619380 79f89b6918a3d9969d3be3e70a8e8b68d6b1ad76
push id71657
push userbmo:jld@mozilla.com
push dateTue, 01 Aug 2017 22:54:28 +0000
reviewersgcp
bugs1384986
milestone56.0a1
Bug 1384986 - Fix DConf breakage caused by read restrictions. r=gcp MozReview-Commit-ID: GKTBPtAea5J
security/sandbox/linux/broker/SandboxBroker.cpp
security/sandbox/linux/broker/SandboxBroker.h
security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
--- a/security/sandbox/linux/broker/SandboxBroker.cpp
+++ b/security/sandbox/linux/broker/SandboxBroker.cpp
@@ -276,16 +276,36 @@ SandboxBroker::Policy::AddDynamic(int aP
     if (aPath[len - 1] == '/') {
       AddDir(aPerms, aPath);
     } else {
       AddPath(aPerms, aPath);
     }
   }
 }
 
+void
+SandboxBroker::Policy::AddAncestors(const char* aPath)
+{
+  AddAncestors(nsAutoCString(aPath));
+}
+
+void
+SandboxBroker::Policy::AddAncestors(nsCString&& aPath)
+{
+  while (true) {
+    const auto lastSlash = aPath.RFindCharInSet("/");
+    if (lastSlash <= 0) {
+      MOZ_ASSERT(lastSlash == 0);
+      break;
+    }
+    aPath.Truncate(lastSlash);
+    AddPath(MAY_ACCESS, aPath.get());
+  }
+}
+
 int
 SandboxBroker::Policy::Lookup(const nsACString& aPath) const
 {
   // Early exit for paths explicitly found in the
   // whitelist.
   // This means they will not gain extra permissions
   // from recursive paths.
   int perms = mMap.Get(aPath);
--- a/security/sandbox/linux/broker/SandboxBroker.h
+++ b/security/sandbox/linux/broker/SandboxBroker.h
@@ -87,16 +87,23 @@ class SandboxBroker final
     // Adds a file or dir (end with /) if it exists, and a prefix otherwhise.
     void AddDynamic(int aPerms, const char* aPath);
     // Default: add file if it exists when creating policy or if we're
     // conferring permission to create it (log files, etc.).
     void AddPath(int aPerms, const char* aPath) {
       AddPath(aPerms, aPath,
               (aPerms & MAY_CREATE) ? AddAlways : AddIfExistsNow);
     }
+    // Adds MAY_ACCESS for all ancestors of a given path.  Useful for
+    // libraries that try to do the equivalent of `mkdir -p`.  This
+    // does not include the root directory, and it includes the path
+    // itself only if it has a trailing slash.
+    void AddAncestors(const char* aPath);
+    void AddAncestors(nsCString&& aPath);
+
     int Lookup(const nsACString& aPath) const;
     int Lookup(const char* aPath) const {
       return Lookup(nsDependentCString(aPath));
     }
   private:
     // ValidatePath checks |path| and returns true if these conditions are met
     // * Greater than 0 length
     // * Is an absolute path
--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
@@ -79,16 +79,17 @@ SandboxBrokerPolicyFactory::SandboxBroke
 #endif
 
 #ifdef MOZ_WIDGET_GTK
   // Bug 1321134: DConf's single bit of shared memory
   if (const auto userDir = g_get_user_runtime_dir()) {
     // The leaf filename is "user" by default, but is configurable.
     nsPrintfCString shmPath("%s/dconf/", userDir);
     policy->AddPrefix(rdwrcr, shmPath.get());
+    policy->AddAncestors(Move(shmPath));
   }
 #endif
 
   // Read permissions
   // No read blocking at level 2 and below
   if (Preferences::GetInt("security.sandbox.content.level") <= 2) {
     policy->AddDir(rdonly, "/");
     mCommonContentPolicy.reset(policy);