Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2525)

Unified Diff: base/file_util_unittest.cc

Issue 7718021: Add external extensions json source in proper mac location. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use IsParent() Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/file_util_unittest.cc
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index c44b804f00949c85b4fd877c261e85f45a9155a6..c5a7b284ad6b6b4a3b67147f93ce4ad5998e1e33 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -110,6 +110,27 @@ bool DeleteReparsePoint(HANDLE source) {
}
#endif
+#if defined(OS_POSIX)
+// Provide a simple way to change the permissions bits on |path| in tests.
+// ASSERT failures will return, but not stop the test. Caller should wrap
+// calls to this function in ASSERT_NO_FATAL_FAILURE().
+void ChangePosixFilePermissions(const FilePath& path,
+ mode_t mode_bits_to_set,
+ mode_t mode_bits_to_clear) {
+ ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
+ << "Can't set and clear the same bits.";
+
+ struct stat stat_buf;
+ ASSERT_EQ(0, stat(path.value().c_str(), &stat_buf));
+
+ mode_t new_mode_bits = stat_buf.st_mode;
+ new_mode_bits |= mode_bits_to_set;
+ new_mode_bits &= ~mode_bits_to_clear;
+
+ ASSERT_EQ(0, chmod(path.value().c_str(), new_mode_bits));
+}
+#endif // defined(OS_POSIX)
+
const wchar_t bogus_content[] = L"I'm cannon fodder.";
const file_util::FileEnumerator::FileType FILES_AND_DIRECTORIES =
@@ -1813,4 +1834,225 @@ TEST_F(FileUtilTest, IsDirectoryEmpty) {
EXPECT_FALSE(file_util::IsDirectoryEmpty(empty_dir));
}
+#if defined(OS_POSIX)
+
+// Testing IsPathControlledByAdmin() is hard, because there is no
+// way a test can make a file owned by root, or change file paths
+// at the root of the file system. IsPathControlledByAdmin()
+// is implemented as a call to IsPathControlledByUser, which gives
+// us the ability to test with paths under the test's temp directory,
+// using a user id we control.
+// Pull tests of IsPathControlledByUserTest() into a separate test class
+// with a common SetUp() method.
+class IsPathControlledByUserTest : public FileUtilTest {
+ protected:
+ virtual void SetUp() {
+ FileUtilTest::SetUp();
+
+ // Create a basic structure used by each test.
+ // base_dir_
+ // |-> sub_dir_
+ // |-> text_file_
+
+ base_dir_ = temp_dir_.path().AppendASCII("base_dir");
+ ASSERT_TRUE(file_util::CreateDirectory(base_dir_));
+
+ sub_dir_ = base_dir_.AppendASCII("sub_dir");
+ ASSERT_TRUE(file_util::CreateDirectory(sub_dir_));
+
+ text_file_ = sub_dir_.AppendASCII("file.txt");
+ CreateTextFile(text_file_, L"This text file has some text in it.");
Evan Martin 2011/08/30 17:26:38 Are your tests vulnerable to the umask? I wonder
Sam Kerner (Chrome) 2011/09/16 18:12:59 I explicitly set the permissions bits here. Each
+
+ // Our user and group id.
+ uid_ = getuid();
+ gid_ = getgid();
+ }
+
+ FilePath base_dir_;
+ FilePath sub_dir_;
+ FilePath text_file_;
+ uid_t uid_;
+ gid_t gid_;
+};
+
+TEST_F(IsPathControlledByUserTest, BadPaths) {
+ // File does not exist.
+ FilePath does_not_exist = base_dir_.AppendASCII("does")
+ .AppendASCII("not")
+ .AppendASCII("exist");
+
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, does_not_exist, uid_, gid_));
+
+ // |base| not a subpath of |path|.
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, base_dir_, uid_, gid_));
+
+ // An empty base path will fail to be a prefix for any path.
+ FilePath empty;
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(empty, base_dir_, uid_, gid_));
+
+ // Finding that a bad call fails proves nothing unless a good call succeeds.
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+}
+
+TEST_F(IsPathControlledByUserTest, Symlinks) {
+ // Symlinks in the path should cause failure.
+
+ // Symlink to the file at the end of the path.
+ FilePath file_link = base_dir_.AppendASCII("file_link");
+ ASSERT_TRUE(file_util::CreateSymbolicLink(text_file_, file_link))
+ << "Failed to create symlink.";
+
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, file_link, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(file_link, file_link, uid_, gid_));
+
+ // Symlink from one directory to another within the path.
+ FilePath link_to_sub_dir_ = base_dir_.AppendASCII("link_to_sub_dir_");
+ ASSERT_TRUE(file_util::CreateSymbolicLink(sub_dir_, link_to_sub_dir_))
Evan Martin 2011/08/30 17:26:38 Heh, the trailing underscore bled into the directo
Sam Kerner (Chrome) 2011/09/16 18:12:59 Search and replace was a bit too effective. Fixed
+ << "Failed to create symlink.";
+
+ FilePath file_path_with_link = link_to_sub_dir_.AppendASCII("file.txt");
+ ASSERT_TRUE(file_util::PathExists(file_path_with_link));
+
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(
+ base_dir_, file_path_with_link, uid_, gid_));
+
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(
+ link_to_sub_dir_, file_path_with_link, uid_, gid_));
+
+ // Symlinks in parents of base path are allowed.
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(
+ file_path_with_link, file_path_with_link, uid_, gid_));
+}
+
+TEST_F(IsPathControlledByUserTest, 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));
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
+
+ // We control these paths.
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Another user does not control these paths.
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, bad_uid, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, bad_uid, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, bad_uid, gid_));
+
+ // Another group does not control the paths.
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gid));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, bad_gid));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, bad_gid));
+}
+
+TEST_F(IsPathControlledByUserTest, WriteBitChecks) {
+
+ // Make all files and directories non-world-writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
+
+ // Initialy, we control all parts of teh path.
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Make base_dir_ world-writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Make sub_dir_ world writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Make text_file_ world writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Make sub_dir_ non-world writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // Make base_dir_ non-world-writable.
+ ASSERT_NO_FATAL_FAILURE(
+ ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_FALSE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+
+ // 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::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_));
+ EXPECT_TRUE(
+ file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_));
+}
+
+#endif // defined(OS_POSIX)
+
} // namespace

Powered by Google App Engine
This is Rietveld 408576698