| Index: chrome/common/sandbox_mac.mm
|
| diff --git a/chrome/common/sandbox_mac.mm b/chrome/common/sandbox_mac.mm
|
| index 608ba27b5691e5d33f10f7666e7997927ffd03fa..1940c60ec5179a2affbd7b8d0aaa8743abd6be6b 100644
|
| --- a/chrome/common/sandbox_mac.mm
|
| +++ b/chrome/common/sandbox_mac.mm
|
| @@ -242,6 +242,78 @@ void SandboxWarmup() {
|
| }
|
| }
|
|
|
| +// Build the Sandbox command necessary to allow access to a named directory
|
| +// indicated by |allowed_dir|.
|
| +// returns a string containing the sandbox profile commands necesary to allow
|
| +// access to that directory or nil if an error occured.
|
| +NSString* BuildAllowDirectoryAccessSandboxString(const FilePath& allowed_dir) {
|
| + // A whitelist is used to determine which directories can be statted
|
| + // This means that in the case of an /a/b/c/d/ directory, we may be able to
|
| + // stat the leaf directory, but not it's parent.
|
| + // The extension code in Chrome calls realpath() which fails if it can't call
|
| + // stat() on one of the parent directories in the path.
|
| + // The solution to this is to allow statting the parent directories themselves
|
| + // but not their contents. We need to add a separate rule for each parent
|
| + // directory.
|
| +
|
| + // The sandbox only understands "real" paths. This resolving step is
|
| + // needed so the caller doesn't need to worry about things like /var
|
| + // being a link to /private/var (like in the paths CreateNewTempDirectory()
|
| + // returns).
|
| + FilePath allowed_dir_canonical(allowed_dir);
|
| + GetCanonicalSandboxPath(&allowed_dir_canonical);
|
| +
|
| + // Collect a list of all parent directories.
|
| + FilePath last_path = allowed_dir_canonical;
|
| + std::vector<FilePath> subpaths;
|
| + for (FilePath path = allowed_dir_canonical.DirName();
|
| + path.value() != last_path.value();
|
| + path = path.DirName()) {
|
| + subpaths.push_back(path);
|
| + last_path = path;
|
| + }
|
| +
|
| + // Iterate through all parents and allow stat() on them explicitly.
|
| + NSString* sandbox_command = @"(allow file-read-metadata ";
|
| + for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
|
| + i != subpaths.rend();
|
| + ++i) {
|
| + std::string subdir_escaped;
|
| + if (!QuotePlainString(i->value(), &subdir_escaped)) {
|
| + LOG(FATAL) << "String quoting failed " << i->value();
|
| + return nil;
|
| + }
|
| +
|
| + NSString* subdir_escaped_ns =
|
| + base::SysUTF8ToNSString(subdir_escaped.c_str());
|
| + sandbox_command =
|
| + [sandbox_command stringByAppendingFormat:@"(literal \"%@\")",
|
| + subdir_escaped_ns];
|
| + }
|
| +
|
| + // Finally append the leaf directory. Unlike it's parents (for which only
|
| + // stat() should be allowed), the leaf directory needs full access.
|
| + sandbox_command =
|
| + [sandbox_command
|
| + stringByAppendingString:@") (allow file-read* file-write* "];
|
| +
|
| + std::string allowed_dir_escaped;
|
| + if (!QuoteStringForRegex(allowed_dir_canonical.value(),
|
| + &allowed_dir_escaped)) {
|
| + LOG(FATAL) << "Regex string quoting failed "
|
| + << allowed_dir_canonical.value();
|
| + return nil;
|
| + }
|
| +
|
| + NSString* allowed_dir_canonical_ns =
|
| + base::SysUTF8ToNSString(allowed_dir_escaped.c_str());
|
| + sandbox_command =
|
| + [sandbox_command stringByAppendingFormat:@"(regex #\"%@\") )",
|
| + allowed_dir_canonical_ns];
|
| +
|
| + return sandbox_command;
|
| +}
|
| +
|
| // Turns on the OS X sandbox for this process.
|
| bool EnableSandbox(SandboxProcessType sandbox_type,
|
| const FilePath& allowed_dir) {
|
| @@ -341,28 +413,14 @@ bool EnableSandbox(SandboxProcessType sandbox_type,
|
| }
|
|
|
| if (!allowed_dir.empty()) {
|
| - // The sandbox only understands "real" paths. This resolving step is
|
| - // needed so the caller doesn't need to worry about things like /var
|
| - // being a link to /private/var (like in the paths CreateNewTempDirectory()
|
| - // returns).
|
| - FilePath allowed_dir_canonical(allowed_dir);
|
| - GetCanonicalSandboxPath(&allowed_dir_canonical);
|
| -
|
| - std::string allowed_dir_escaped;
|
| - if (!QuoteStringForRegex(allowed_dir_canonical.value(),
|
| - &allowed_dir_escaped)) {
|
| - LOG(FATAL) << "Regex string quoting failed " << allowed_dir.value();
|
| - return false;
|
| - }
|
| - NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString(
|
| - allowed_dir_escaped.c_str());
|
| - sandbox_data = [sandbox_data
|
| - stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
|
| - withString:@""];
|
| - sandbox_data = [sandbox_data
|
| - stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
|
| - withString:allowed_dir_escaped_ns];
|
| + NSString* allowed_dir_sandbox_command =
|
| + BuildAllowDirectoryAccessSandboxString(allowed_dir);
|
|
|
| + if (allowed_dir_sandbox_command) { // May be nil if function fails.
|
| + sandbox_data = [sandbox_data
|
| + stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
|
| + withString:allowed_dir_sandbox_command];
|
| + }
|
| }
|
|
|
| if (snow_leopard_or_higher) {
|
|
|