| Index: chrome/common/sandbox_mac_diraccess_unittest.mm
|
| diff --git a/chrome/common/sandbox_mac_diraccess_unittest.mm b/chrome/common/sandbox_mac_diraccess_unittest.mm
|
| index 580436118b61c9d78c392efd8536c514422178a9..1f9a1d466ea127ce42dbfa8ed5b0cbbaa9be3d63 100644
|
| --- a/chrome/common/sandbox_mac_diraccess_unittest.mm
|
| +++ b/chrome/common/sandbox_mac_diraccess_unittest.mm
|
| @@ -24,12 +24,14 @@ namespace sandbox {
|
|
|
| bool QuotePlainString(const std::string& str_utf8, std::string* dst);
|
| bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst);
|
| +NSString* BuildAllowDirectoryAccessSandboxString(const FilePath& allowed_dir);
|
|
|
| } // namespace sandbox
|
|
|
| namespace {
|
|
|
| static const char* kSandboxAccessPathKey = "sandbox_dir";
|
| +static const char* kDeniedSuffix = "_denied";
|
|
|
| class MacDirAccessSandboxTest : public base::MultiProcessTest {
|
| public:
|
| @@ -143,8 +145,9 @@ class ScopedDirectoryDelete {
|
|
|
| typedef scoped_ptr_malloc<FilePath, ScopedDirectoryDelete> ScopedDirectory;
|
|
|
| -// Crashy, http://crbug.com/56765.
|
| -TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
|
| +TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
|
| + using file_util::CreateDirectory;
|
| +
|
| FilePath tmp_dir;
|
| ASSERT_TRUE(file_util::CreateNewTempDirectory("", &tmp_dir));
|
| // This step is important on OS X since the sandbox only understands "real"
|
| @@ -162,8 +165,18 @@ TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
|
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(sandbox_dir_cases); ++i) {
|
| const char* sandbox_dir_name = sandbox_dir_cases[i];
|
| FilePath sandbox_dir = tmp_dir.Append(sandbox_dir_name);
|
| - ASSERT_TRUE(file_util::CreateDirectory(sandbox_dir));
|
| + ASSERT_TRUE(CreateDirectory(sandbox_dir));
|
| ScopedDirectory cleanup_sandbox(&sandbox_dir);
|
| +
|
| + // Create a sibling directory of the sandbox dir, whose name has sandbox dir
|
| + // as a substring but to which access is denied.
|
| + std::string sibling_sandbox_dir_name_denied =
|
| + std::string(sandbox_dir_cases[i]) + kDeniedSuffix;
|
| + FilePath sibling_sandbox_dir = tmp_dir.Append(
|
| + sibling_sandbox_dir_name_denied.c_str());
|
| + ASSERT_TRUE(CreateDirectory(sibling_sandbox_dir));
|
| + ScopedDirectory cleanup_sandbox_sibling(&sibling_sandbox_dir);
|
| +
|
| EXPECT_TRUE(CheckSandbox(sandbox_dir.value()));
|
| }
|
| }
|
| @@ -173,14 +186,13 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
|
| if (!sandbox_allowed_dir)
|
| return -1;
|
|
|
| - // Build up a sandbox profile that only allows access to DIR_TO_ALLOW_ACCESS.
|
| + // Build up a sandbox profile that only allows access to a single directory.
|
| NSString *sandbox_profile =
|
| @"(version 1)" \
|
| "(deny default)" \
|
| "(allow signal (target self))" \
|
| "(allow sysctl-read)" \
|
| - "(allow file-read-metadata)" \
|
| - "(allow file-read* file-write* (regex #\"DIR_TO_ALLOW_ACCESS\"))";
|
| + ";ENABLE_DIRECTORY_ACCESS";
|
|
|
| std::string allowed_dir(sandbox_allowed_dir);
|
| std::string allowed_dir_escaped;
|
| @@ -188,11 +200,12 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
|
| LOG(ERROR) << "Regex string quoting failed " << allowed_dir;
|
| return -1;
|
| }
|
| - NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString(
|
| - allowed_dir_escaped.c_str());
|
| + NSString* allow_dir_sandbox_code =
|
| + sandbox::BuildAllowDirectoryAccessSandboxString(
|
| + FilePath(sandbox_allowed_dir));
|
| sandbox_profile = [sandbox_profile
|
| - stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
|
| - withString:allowed_dir_escaped_ns];
|
| + stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
|
| + withString:allow_dir_sandbox_code];
|
| // Enable Sandbox.
|
| char* error_buff = NULL;
|
| int error = sandbox_init([sandbox_profile UTF8String], 0, &error_buff);
|
| @@ -223,8 +236,9 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
|
| // Try to write a file who's name has the same prefix as the directory we
|
| // allow access to.
|
| FilePath basename = allowed_dir_path.BaseName();
|
| + FilePath allowed_parent_dir = allowed_dir_path.DirName();
|
| std::string tricky_filename = basename.value() + "123";
|
| - FilePath denied_file2 = allowed_dir_path.DirName().Append(tricky_filename);
|
| + FilePath denied_file2 = allowed_parent_dir.Append(tricky_filename);
|
|
|
| if (open(allowed_file.value().c_str(), O_WRONLY | O_CREAT) <= 0) {
|
| PLOG(ERROR) << "Sandbox overly restrictive: failed to write ("
|
| @@ -233,6 +247,43 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
|
| return -1;
|
| }
|
|
|
| + // Test that we deny access to a sibling of the sandboxed directory whose
|
| + // name has the sandboxed directory name as a substring. e.g. if the sandbox
|
| + // directory is /foo/baz then test /foo/baz_denied.
|
| + {
|
| + struct stat tmp_stat_info;
|
| + std::string denied_sibling =
|
| + std::string(sandbox_allowed_dir) + kDeniedSuffix;
|
| + if (stat(denied_sibling.c_str(), &tmp_stat_info) > 0) {
|
| + PLOG(ERROR) << "Sandbox breach: was able to stat ("
|
| + << denied_sibling.c_str()
|
| + << ")";
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| + // Test that we can stat parent directories of the "allowed" directory.
|
| + {
|
| + struct stat tmp_stat_info;
|
| + if (stat(allowed_parent_dir.value().c_str(), &tmp_stat_info) != 0) {
|
| + PLOG(ERROR) << "Sandbox overly restrictive: unable to stat ("
|
| + << allowed_parent_dir.value()
|
| + << ")";
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| + // Test that we can't stat files outside the "allowed" directory.
|
| + {
|
| + struct stat tmp_stat_info;
|
| + if (stat(denied_file1.value().c_str(), &tmp_stat_info) > 0) {
|
| + PLOG(ERROR) << "Sandbox breach: was able to stat ("
|
| + << denied_file1.value()
|
| + << ")";
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| if (open(denied_file1.value().c_str(), O_WRONLY | O_CREAT) > 0) {
|
| PLOG(ERROR) << "Sandbox breach: was able to write ("
|
| << denied_file1.value()
|
|
|