summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-12 15:13:57 +0000
committerskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-12 15:13:57 +0000
commit01e2a1fabe5a6d0065f535a9de4bdd98f0640906 (patch)
tree2050dd5669e2907324d13002cb261ffa15c8d1f9
parent4979b09a75936283a62772b7078de381d60061fc (diff)
downloadchromium_src-01e2a1fabe5a6d0065f535a9de4bdd98f0640906.zip
chromium_src-01e2a1fabe5a6d0065f535a9de4bdd98f0640906.tar.gz
chromium_src-01e2a1fabe5a6d0065f535a9de4bdd98f0640906.tar.bz2
Use realpath() to find the path to the extension unpack dir on posix systems.
Extensions are unpacked by a sandboxed utility process. The sandbox forbids file access outside the directory the extension will be unpacked in. If the path to that directory contains a symbolic link, then unpacking will fail because following the link will cause file system access outside the sandbox path. Use realpath() to get a symlink free path to the directory where the extension will be unpacked. A similar issue exists on windows, with junctions instead of symlinks. This will be fixed in another change. BUG=13044,35198 TEST=FileUtilTest.RealPath Review URL: http://codereview.chromium.org/2001013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47032 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/file_util.h7
-rw-r--r--base/file_util_posix.cc10
-rw-r--r--base/file_util_unittest.cc51
-rw-r--r--chrome/browser/utility_process_host.cc25
4 files changed, 92 insertions, 1 deletions
diff --git a/base/file_util.h b/base/file_util.h
index a129876..64a91ee 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -279,6 +279,13 @@ bool IsDot(const FilePath& path);
// Returns true if the given path's base name is "..".
bool IsDotDot(const FilePath& path);
+#if defined(OS_POSIX)
+// Set |real_path| to |path| with symbolic links expanded.
+// Windows support (expanding junctions) comming soon:
+// http://crbug.com/13044
+bool RealPath(const FilePath& path, FilePath* real_path);
+#endif
+
// Used to hold information about a given file path. See GetFileInfo below.
struct FileInfo {
// The size of the file in bytes. Undefined when is_directory is true.
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index d9cbe09..9db41fe 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -14,6 +14,7 @@
#include <string.h>
#include <sys/errno.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -735,6 +736,15 @@ bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo& find_info,
return find_info.stat.st_mtime >= cutoff_time.ToTimeT();
}
+bool RealPath(const FilePath& path, FilePath* real_path) {
+ FilePath::CharType buf[PATH_MAX];
+ if (!realpath(path.value().c_str(), buf))
+ return false;
+
+ *real_path = FilePath(buf);
+ return true;
+}
+
#if !defined(OS_MACOSX)
bool GetTempDir(FilePath* path) {
const char* tmp = getenv("TMPDIR");
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index c496290..efe79c9 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -387,6 +387,57 @@ TEST_F(FileUtilTest, FileAndDirectorySize) {
EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
}
+#if defined(OS_POSIX)
+TEST_F(FileUtilTest, RealPath) {
+ // Get the real test directory, in case some future change to the
+ // test setup makes the path to test_dir_ include a symlink.
+ FilePath real_test_dir;
+ ASSERT_TRUE(file_util::RealPath(test_dir_, &real_test_dir));
+
+ FilePath real_path;
+ ASSERT_TRUE(file_util::RealPath(real_test_dir, &real_path));
+ ASSERT_TRUE(real_test_dir == real_path);
+
+ // Link one file to another.
+ FilePath link_from = real_test_dir.Append(FPL("from_file"));
+ FilePath link_to = real_test_dir.Append(FPL("to_file"));
+ CreateTextFile(link_to, bogus_content);
+
+ ASSERT_EQ(0, symlink(link_to.value().c_str(), link_from.value().c_str()))
+ << "Failed to create file symlink.";
+
+ // Check that RealPath sees the link.
+ ASSERT_TRUE(file_util::RealPath(link_from, &real_path));
+ ASSERT_TRUE(link_to != link_from);
+ ASSERT_TRUE(link_to == real_path);
+
+
+ // Link to a directory.
+ link_from = real_test_dir.Append(FPL("from_dir"));
+ link_to = real_test_dir.Append(FPL("to_dir"));
+ file_util::CreateDirectory(link_to);
+
+ ASSERT_EQ(0, symlink(link_to.value().c_str(), link_from.value().c_str()))
+ << "Failed to create directory symlink.";
+
+ ASSERT_TRUE(file_util::RealPath(link_from, &real_path));
+ ASSERT_TRUE(link_to != link_from);
+ ASSERT_TRUE(link_to == real_path);
+
+
+ // Test that a loop in the links causes RealPath() to return false.
+ link_from = real_test_dir.Append(FPL("link_a"));
+ link_to = real_test_dir.Append(FPL("link_b"));
+ ASSERT_EQ(0, symlink(link_to.value().c_str(), link_from.value().c_str()))
+ << "Failed to create loop symlink a.";
+ ASSERT_EQ(0, symlink(link_from.value().c_str(), link_to.value().c_str()))
+ << "Failed to create loop symlink b.";
+
+ // Infinite loop!
+ ASSERT_FALSE(file_util::RealPath(link_from, &real_path));
+}
+#endif // defined(OS_POSIX)
+
TEST_F(FileUtilTest, DeleteNonExistent) {
FilePath non_existent = test_dir_.AppendASCII("bogus_file_dne.foobar");
ASSERT_FALSE(file_util::PathExists(non_existent));
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 2f7ce5d..118234d7e 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -26,9 +26,32 @@ UtilityProcessHost::~UtilityProcessHost() {
}
bool UtilityProcessHost::StartExtensionUnpacker(const FilePath& extension) {
+ FilePath initial_path = extension.DirName();
+ FilePath real_path;
+
+ // The utility process will have access to the directory passed to
+ // StartProcess(). That directory should not be a symlink or NTFS
+ // junctions, because when the path is used, following the link will
+ // cause file system access outside the sandbox path.
+
+#if defined(OS_POSIX)
+ // Resolve symlinks to get a symlink free path.
+ if (!file_util::RealPath(initial_path, &real_path)) {
+ real_path = initial_path;
+ }
+#else
+ // TODO(skerner): For windows, we need to expand NTFS junctions.
+ // http://crbug.com/13044
+ real_path = initial_path;
+#endif
+
+ // TODO(skerner): Remove this logging once we understand crbug.com/35198
+ LOG(INFO) << "initial_path: " << initial_path.value();
+ LOG(INFO) << "real_path: " << real_path.value();
+
// Grant the subprocess access to the entire subdir the extension file is
// in, so that it can unpack to that dir.
- if (!StartProcess(extension.DirName()))
+ if (!StartProcess(real_path))
return false;
Send(new UtilityMsg_UnpackExtension(extension));