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

Side by Side Diff: content/common/sandbox_mac.mm

Issue 10539009: mac: Make the (10.6-only) sandbox hole for the components build smaller (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: test Created 8 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/common/sandbox_mac.h ('k') | content/common/sandbox_mac_diraccess_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/sandbox_mac.h" 5 #include "content/common/sandbox_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 extern "C" { 9 extern "C" {
10 #include <sandbox.h> 10 #include <sandbox.h>
11 } 11 }
12 #include <signal.h> 12 #include <signal.h>
13 #include <sys/param.h> 13 #include <sys/param.h>
14 14
15 #include "base/basictypes.h" 15 #include "base/basictypes.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/compiler_specific.h" 17 #include "base/compiler_specific.h"
18 #include "base/file_util.h" 18 #include "base/file_util.h"
19 #include "base/mac/bundle_locations.h"
19 #include "base/mac/mac_util.h" 20 #include "base/mac/mac_util.h"
20 #include "base/mac/scoped_cftyperef.h" 21 #include "base/mac/scoped_cftyperef.h"
21 #include "base/mac/scoped_nsautorelease_pool.h" 22 #include "base/mac/scoped_nsautorelease_pool.h"
22 #include "base/memory/scoped_nsobject.h" 23 #include "base/memory/scoped_nsobject.h"
23 #include "base/rand_util.h" 24 #include "base/rand_util.h"
24 #include "base/string16.h" 25 #include "base/string16.h"
25 #include "base/string_piece.h" 26 #include "base/string_piece.h"
26 #include "base/string_util.h" 27 #include "base/string_util.h"
27 #include "base/stringprintf.h" 28 #include "base/stringprintf.h"
28 #include "base/sys_info.h" 29 #include "base/sys_info.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 // Copy bad string to the stack so it's recorded in the crash dump. 99 // Copy bad string to the stack so it's recorded in the crash dump.
99 char bad_string[256] = {0}; 100 char bad_string[256] = {0};
100 base::strlcpy(bad_string, str.c_str(), arraysize(bad_string)); 101 base::strlcpy(bad_string, str.c_str(), arraysize(bad_string));
101 DLOG(FATAL) << "String quoting failed " << bad_string; 102 DLOG(FATAL) << "String quoting failed " << bad_string;
102 } 103 }
103 104
104 } // namespace 105 } // namespace
105 106
106 namespace sandbox { 107 namespace sandbox {
107 108
109 // static
110 NSString* Sandbox::AllowMetadataForPath(const FilePath& allowed_path) {
111 // Collect a list of all parent directories.
112 FilePath last_path = allowed_path;
113 std::vector<FilePath> subpaths;
114 for (FilePath path = allowed_path;
Jiang Jiang 2014/08/13 10:48:08 This seems wrong as the original code is: for (Fi
Nico 2014/08/13 15:43:17 Hm, that seems right. I guess noone uses the compo
115 path.value() != last_path.value();
116 path = path.DirName()) {
117 subpaths.push_back(path);
118 last_path = path;
119 }
120
121 // Iterate through all parents and allow stat() on them explicitly.
122 NSString* sandbox_command = @"(allow file-read-metadata ";
123 for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
124 i != subpaths.rend();
125 ++i) {
126 std::string subdir_escaped;
127 if (!QuotePlainString(i->value(), &subdir_escaped)) {
128 FatalStringQuoteException(i->value());
129 return nil;
130 }
131
132 NSString* subdir_escaped_ns =
133 base::SysUTF8ToNSString(subdir_escaped.c_str());
134 sandbox_command =
135 [sandbox_command stringByAppendingFormat:@"(literal \"%@\")",
136 subdir_escaped_ns];
137 }
138
139 return [sandbox_command stringByAppendingString:@")"];
140 }
108 141
109 // static 142 // static
110 bool Sandbox::QuotePlainString(const std::string& src_utf8, std::string* dst) { 143 bool Sandbox::QuotePlainString(const std::string& src_utf8, std::string* dst) {
111 dst->clear(); 144 dst->clear();
112 145
113 const char* src = src_utf8.c_str(); 146 const char* src = src_utf8.c_str();
114 int32_t length = src_utf8.length(); 147 int32_t length = src_utf8.length();
115 int32_t position = 0; 148 int32_t position = 0;
116 while (position < length) { 149 while (position < length) {
117 UChar32 c; 150 UChar32 c;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // The extension code in Chrome calls realpath() which fails if it can't call 320 // The extension code in Chrome calls realpath() which fails if it can't call
288 // stat() on one of the parent directories in the path. 321 // stat() on one of the parent directories in the path.
289 // The solution to this is to allow statting the parent directories themselves 322 // The solution to this is to allow statting the parent directories themselves
290 // but not their contents. We need to add a separate rule for each parent 323 // but not their contents. We need to add a separate rule for each parent
291 // directory. 324 // directory.
292 325
293 // The sandbox only understands "real" paths. This resolving step is 326 // The sandbox only understands "real" paths. This resolving step is
294 // needed so the caller doesn't need to worry about things like /var 327 // needed so the caller doesn't need to worry about things like /var
295 // being a link to /private/var (like in the paths CreateNewTempDirectory() 328 // being a link to /private/var (like in the paths CreateNewTempDirectory()
296 // returns). 329 // returns).
297 FilePath allowed_dir_canonical(allowed_dir); 330 FilePath allowed_dir_canonical = GetCanonicalSandboxPath(allowed_dir);
298 GetCanonicalSandboxPath(&allowed_dir_canonical);
299 331
300 // Collect a list of all parent directories. 332 NSString* sandbox_command = AllowMetadataForPath(allowed_dir_canonical);
301 FilePath last_path = allowed_dir_canonical; 333 sandbox_command = [sandbox_command
302 std::vector<FilePath> subpaths; 334 substringToIndex:[sandbox_command length] - 1]; // strip trailing ')'
303 for (FilePath path = allowed_dir_canonical.DirName();
304 path.value() != last_path.value();
305 path = path.DirName()) {
306 subpaths.push_back(path);
307 last_path = path;
308 }
309
310 // Iterate through all parents and allow stat() on them explicitly.
311 NSString* sandbox_command = @"(allow file-read-metadata ";
312 for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
313 i != subpaths.rend();
314 ++i) {
315 std::string subdir_escaped;
316 if (!QuotePlainString(i->value(), &subdir_escaped)) {
317 FatalStringQuoteException(i->value());
318 return nil;
319 }
320
321 NSString* subdir_escaped_ns =
322 base::SysUTF8ToNSString(subdir_escaped.c_str());
323 sandbox_command =
324 [sandbox_command stringByAppendingFormat:@"(literal \"%@\")",
325 subdir_escaped_ns];
326 }
327 335
328 // Finally append the leaf directory. Unlike its parents (for which only 336 // Finally append the leaf directory. Unlike its parents (for which only
329 // stat() should be allowed), the leaf directory needs full access. 337 // stat() should be allowed), the leaf directory needs full access.
330 (*substitutions)["ALLOWED_DIR"] = 338 (*substitutions)["ALLOWED_DIR"] =
331 SandboxSubstring(allowed_dir_canonical.value(), 339 SandboxSubstring(allowed_dir_canonical.value(),
332 SandboxSubstring::REGEX); 340 SandboxSubstring::REGEX);
333 sandbox_command = 341 sandbox_command =
334 [sandbox_command 342 [sandbox_command
335 stringByAppendingString:@") (allow file-read* file-write*" 343 stringByAppendingString:@") (allow file-read* file-write*"
336 " (regex #\"@ALLOWED_DIR@\") )"]; 344 " (regex #\"@ALLOWED_DIR@\") )"];
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] = 525 substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] =
518 SandboxSubstring("(with no-log)"); 526 SandboxSubstring("(with no-log)");
519 } else { 527 } else {
520 substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] = SandboxSubstring(""); 528 substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] = SandboxSubstring("");
521 } 529 }
522 530
523 // Splice the path of the user's home directory into the sandbox profile 531 // Splice the path of the user's home directory into the sandbox profile
524 // (see renderer.sb for details). 532 // (see renderer.sb for details).
525 std::string home_dir = [NSHomeDirectory() fileSystemRepresentation]; 533 std::string home_dir = [NSHomeDirectory() fileSystemRepresentation];
526 534
527 FilePath home_dir_canonical(home_dir); 535 FilePath home_dir_canonical = GetCanonicalSandboxPath(FilePath(home_dir));
528 GetCanonicalSandboxPath(&home_dir_canonical);
529 536
530 substitutions["USER_HOMEDIR_AS_LITERAL"] = 537 substitutions["USER_HOMEDIR_AS_LITERAL"] =
531 SandboxSubstring(home_dir_canonical.value(), 538 SandboxSubstring(home_dir_canonical.value(),
532 SandboxSubstring::LITERAL); 539 SandboxSubstring::LITERAL);
533 540
534 if (lion_or_later) { 541 if (lion_or_later) {
535 // >=10.7 Sandbox rules. 542 // >=10.7 Sandbox rules.
536 [tokens_to_remove addObject:@";10.7_OR_ABOVE"]; 543 [tokens_to_remove addObject:@";10.7_OR_ABOVE"];
537 } 544 }
538 545
539 if (snow_leopard_or_later) { 546 if (snow_leopard_or_later) {
540 // >=10.6 Sandbox rules. 547 // >=10.6 Sandbox rules.
541 [tokens_to_remove addObject:@";10.6_OR_ABOVE"]; 548 [tokens_to_remove addObject:@";10.6_OR_ABOVE"];
542 } else { 549 } else {
543 // Sandbox rules only for versions before 10.6. 550 // Sandbox rules only for versions before 10.6.
544 [tokens_to_remove addObject:@";BEFORE_10.6"]; 551 [tokens_to_remove addObject:@";BEFORE_10.6"];
545 } 552 }
546 553
547 substitutions["COMPONENT_BUILD_WORKAROUND"] = SandboxSubstring(""); 554 substitutions["COMPONENT_BUILD_WORKAROUND"] = SandboxSubstring("");
548 #if defined(COMPONENT_BUILD) 555 #if defined(COMPONENT_BUILD)
549 // dlopen() fails without file-read-metadata access if the executable image 556 // dlopen() fails without file-read-metadata access if the executable image
550 // contains LC_RPATH load commands. The components build uses those. 557 // contains LC_RPATH load commands. The components build uses those.
551 // See http://crbug.com/127465 558 // See http://crbug.com/127465
552 if (base::mac::IsOSSnowLeopardOrEarlier()) { 559 if (base::mac::IsOSSnowLeopardOrEarlier()) {
560 FilePath bundle_executable = base::mac::NSStringToFilePath(
561 [base::mac::MainBundle() executablePath]);
562 NSString* sandbox_command = AllowMetadataForPath(
563 GetCanonicalSandboxPath(bundle_executable));
553 substitutions["COMPONENT_BUILD_WORKAROUND"] = 564 substitutions["COMPONENT_BUILD_WORKAROUND"] =
554 SandboxSubstring("(allow file-read-metadata)"); 565 SandboxSubstring(base::SysNSStringToUTF8(sandbox_command));
555 } 566 }
556 #endif 567 #endif
557 568
558 // All information needed to assemble the final profile has been collected. 569 // All information needed to assemble the final profile has been collected.
559 // Merge it all together. 570 // Merge it all together.
560 std::string final_sandbox_profile_str; 571 std::string final_sandbox_profile_str;
561 if (!PostProcessSandboxProfile(sandbox_data, tokens_to_remove, substitutions, 572 if (!PostProcessSandboxProfile(sandbox_data, tokens_to_remove, substitutions,
562 &final_sandbox_profile_str)) { 573 &final_sandbox_profile_str)) {
563 return false; 574 return false;
564 } 575 }
565 576
566 // Initialize sandbox. 577 // Initialize sandbox.
567 char* error_buff = NULL; 578 char* error_buff = NULL;
568 int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff); 579 int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff);
569 bool success = (error == 0 && error_buff == NULL); 580 bool success = (error == 0 && error_buff == NULL);
570 DLOG_IF(FATAL, !success) << "Failed to initialize sandbox: " 581 DLOG_IF(FATAL, !success) << "Failed to initialize sandbox: "
571 << error 582 << error
572 << " " 583 << " "
573 << error_buff; 584 << error_buff;
574 sandbox_free_error(error_buff); 585 sandbox_free_error(error_buff);
575 return success; 586 return success;
576 } 587 }
577 588
578 // static 589 // static
579 void Sandbox::GetCanonicalSandboxPath(FilePath* path) { 590 FilePath Sandbox::GetCanonicalSandboxPath(const FilePath& path) {
580 int fd = HANDLE_EINTR(open(path->value().c_str(), O_RDONLY)); 591 int fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY));
581 if (fd < 0) { 592 if (fd < 0) {
582 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " 593 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: "
583 << path->value(); 594 << path.value();
584 return; 595 return path;
585 } 596 }
586 file_util::ScopedFD file_closer(&fd); 597 file_util::ScopedFD file_closer(&fd);
587 598
588 FilePath::CharType canonical_path[MAXPATHLEN]; 599 FilePath::CharType canonical_path[MAXPATHLEN];
589 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { 600 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) {
590 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " 601 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: "
591 << path->value(); 602 << path.value();
592 return; 603 return path;
593 } 604 }
594 605
595 *path = FilePath(canonical_path); 606 return FilePath(canonical_path);
596 } 607 }
597 608
598 } // namespace sandbox 609 } // namespace sandbox
OLDNEW
« no previous file with comments | « content/common/sandbox_mac.h ('k') | content/common/sandbox_mac_diraccess_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698