Update write checks for external extension file on mac.


BUG=100565
TEST=VerifyPathControlledByUserTest.*


Review URL: http://codereview.chromium.org/8318011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105923 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 7312f42a14b8d0717cd44bea53690eb27486e32d
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index b76938e..8ac1076 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -1867,7 +1867,9 @@
     struct stat stat_buf;
     ASSERT_EQ(0, stat(base_dir_.value().c_str(), &stat_buf));
     uid_ = stat_buf.st_uid;
-    gid_ = stat_buf.st_gid;
+    ok_gids_.insert(stat_buf.st_gid);
+    bad_gids_.insert(stat_buf.st_gid + 1);
+
     ASSERT_EQ(uid_, getuid());  // This process should be the owner.
 
     // To ensure that umask settings do not cause the initial state
@@ -1892,7 +1894,9 @@
   FilePath sub_dir_;
   FilePath text_file_;
   uid_t uid_;
-  gid_t gid_;
+
+  std::set<gid_t> ok_gids_;
+  std::set<gid_t> bad_gids_;
 };
 
 TEST_F(VerifyPathControlledByUserTest, BadPaths) {
@@ -1900,23 +1904,25 @@
   FilePath does_not_exist = base_dir_.AppendASCII("does")
                                      .AppendASCII("not")
                                      .AppendASCII("exist");
-
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, does_not_exist, uid_, gid_));
+          base_dir_, does_not_exist, uid_, ok_gids_));
 
   // |base| not a subpath of |path|.
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(sub_dir_, base_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, base_dir_, uid_, ok_gids_));
 
   // An empty base path will fail to be a prefix for any path.
   FilePath empty;
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(empty, base_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          empty, base_dir_, uid_, ok_gids_));
 
   // Finding that a bad call fails proves nothing unless a good call succeeds.
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
 }
 
 TEST_F(VerifyPathControlledByUserTest, Symlinks) {
@@ -1928,9 +1934,11 @@
       << "Failed to create symlink.";
 
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, file_link, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, file_link, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(file_link, file_link, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          file_link, file_link, uid_, ok_gids_));
 
   // Symlink from one directory to another within the path.
   FilePath link_to_sub_dir =  base_dir_.AppendASCII("link_to_sub_dir");
@@ -1942,25 +1950,22 @@
 
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, file_path_with_link, uid_, gid_));
+          base_dir_, file_path_with_link, uid_, ok_gids_));
 
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          link_to_sub_dir, file_path_with_link, uid_, gid_));
+          link_to_sub_dir, file_path_with_link, uid_, ok_gids_));
 
   // Symlinks in parents of base path are allowed.
   EXPECT_TRUE(
       file_util::VerifyPathControlledByUser(
-          file_path_with_link, file_path_with_link, uid_, gid_));
+          file_path_with_link, file_path_with_link, uid_, ok_gids_));
 }
 
 TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
   // Get a uid that is not the uid of files we create.
   uid_t bad_uid = uid_ + 1;
 
-  // Get a gid that is not ours.
-  gid_t bad_gid = gid_ + 1;
-
   // Make all files and directories non-world-writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
@@ -1971,33 +1976,130 @@
 
   // We control these paths.
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Another user does not control these paths.
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, sub_dir_, bad_uid, gid_));
+          base_dir_, sub_dir_, bad_uid, ok_gids_));
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, text_file_, bad_uid, gid_));
+          base_dir_, text_file_, bad_uid, ok_gids_));
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          sub_dir_, text_file_, bad_uid, gid_));
+          sub_dir_, text_file_, bad_uid, ok_gids_));
 
   // Another group does not control the paths.
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, sub_dir_, uid_, bad_gid));
+          base_dir_, sub_dir_, uid_, bad_gids_));
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          base_dir_, text_file_, uid_, bad_gid));
+          base_dir_, text_file_, uid_, bad_gids_));
   EXPECT_FALSE(
       file_util::VerifyPathControlledByUser(
-          sub_dir_, text_file_, uid_, bad_gid));
+          sub_dir_, text_file_, uid_, bad_gids_));
+}
+
+TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
+  // Make all files and directories writable only by their owner.
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH|S_IWGRP));
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH|S_IWGRP));
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(text_file_, 0u, S_IWOTH|S_IWGRP));
+
+  // Any group is okay because the path is not group-writable.
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
+
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, bad_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, bad_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, bad_gids_));
+
+  // No group is okay, because we don't check the group
+  // if no group can write.
+  std::set<gid_t> no_gids;  // Empty set of gids.
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, no_gids));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, no_gids));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, no_gids));
+
+
+  // Make all files and directories writable by their group.
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
+  ASSERT_NO_FATAL_FAILURE(
+      ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
+
+  // Now |ok_gids_| works, but |bad_gids_| fails.
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
+
+  EXPECT_FALSE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, bad_gids_));
+  EXPECT_FALSE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, bad_gids_));
+  EXPECT_FALSE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, bad_gids_));
+
+  // Because any group in the group set is allowed,
+  // the union of good and bad gids passes.
+
+  std::set<gid_t> multiple_gids;
+  std::set_union(
+      ok_gids_.begin(), ok_gids_.end(),
+      bad_gids_.begin(), bad_gids_.end(),
+      std::inserter(multiple_gids, multiple_gids.begin()));
+
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, multiple_gids));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, multiple_gids));
+  EXPECT_TRUE(
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, multiple_gids));
+
 }
 
 TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
@@ -2011,72 +2113,93 @@
 
   // Initialy, we control all parts of the path.
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
    // Make base_dir_ world-writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Make sub_dir_ world writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Make text_file_ world writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Make sub_dir_ non-world writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Make base_dir_ non-world-writable.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_FALSE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 
   // Back to the initial state: Nothing is writable, so every path
   // should pass.
   ASSERT_NO_FATAL_FAILURE(
       ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, sub_dir_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          base_dir_, text_file_, uid_, ok_gids_));
   EXPECT_TRUE(
-      file_util::VerifyPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+      file_util::VerifyPathControlledByUser(
+          sub_dir_, text_file_, uid_, ok_gids_));
 }
 
 #endif  // defined(OS_POSIX)