| Index: base/file_util_unittest.cc
|
| diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
|
| index b76938e6d8ddb48fa44074e9c70117d78011dcc0..8ac10762467ac482698bd6da136c63d16179090f 100644
|
| --- a/base/file_util_unittest.cc
|
| +++ b/base/file_util_unittest.cc
|
| @@ -1867,7 +1867,9 @@ class VerifyPathControlledByUserTest : public FileUtilTest {
|
| 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 @@ class VerifyPathControlledByUserTest : public FileUtilTest {
|
| 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 @@ TEST_F(VerifyPathControlledByUserTest, BadPaths) {
|
| 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 @@ TEST_F(VerifyPathControlledByUserTest, Symlinks) {
|
| << "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 @@ TEST_F(VerifyPathControlledByUserTest, Symlinks) {
|
|
|
| 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 @@ TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
|
|
|
| // 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_gids_));
|
| + EXPECT_FALSE(
|
| + file_util::VerifyPathControlledByUser(
|
| + 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_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_));
|
| +
|
| + // 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 @@ TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
|
|
|
| // 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)
|
|
|