OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/common/sandbox_mac.h" | 5 #include "chrome/common/sandbox_mac.h" |
6 | 6 |
7 #include "base/debug_util.h" | 7 #include "base/debug_util.h" |
8 | 8 |
9 #import <Cocoa/Cocoa.h> | 9 #import <Cocoa/Cocoa.h> |
10 extern "C" { | 10 extern "C" { |
11 #include <sandbox.h> | 11 #include <sandbox.h> |
12 } | 12 } |
| 13 #include <sys/param.h> |
13 | 14 |
14 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
15 #include "base/command_line.h" | 16 #include "base/command_line.h" |
16 #include "base/file_util.h" | 17 #include "base/file_util.h" |
17 #include "base/mac_util.h" | 18 #include "base/mac_util.h" |
18 #include "base/rand_util_c.h" | 19 #include "base/rand_util_c.h" |
19 #include "base/scoped_cftyperef.h" | 20 #include "base/scoped_cftyperef.h" |
20 #include "base/scoped_nsautorelease_pool.h" | 21 #include "base/scoped_nsautorelease_pool.h" |
21 #include "base/string16.h" | 22 #include "base/string16.h" |
22 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 // output. | 112 // output. |
112 // | 113 // |
113 // The implementation of this function is based on empirical testing of the | 114 // The implementation of this function is based on empirical testing of the |
114 // OS X sandbox on 10.5.8 & 10.6.2 which is undocumented and subject to change. | 115 // OS X sandbox on 10.5.8 & 10.6.2 which is undocumented and subject to change. |
115 // | 116 // |
116 // Note: If str_utf8 contains any characters < 32 || >125 then the function | 117 // Note: If str_utf8 contains any characters < 32 || >125 then the function |
117 // fails and false is returned. | 118 // fails and false is returned. |
118 // | 119 // |
119 // Returns: true on success, false otherwise. | 120 // Returns: true on success, false otherwise. |
120 bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst) { | 121 bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst) { |
121 // List of chars with special meaning to regex. | 122 // Characters with special meanings in sandbox profile syntax. |
122 // This list is derived from http://perldoc.perl.org/perlre.html . | |
123 const char regex_special_chars[] = { | 123 const char regex_special_chars[] = { |
124 '\\', | 124 '\\', |
125 | 125 |
126 // Metacharacters | 126 // Metacharacters |
127 '^', | 127 '^', |
128 '.', | 128 '.', |
| 129 '[', |
| 130 ']', |
129 '$', | 131 '$', |
130 '|', | |
131 '(', | 132 '(', |
132 ')', | 133 ')', |
133 '[', | 134 '|', |
134 ']', | |
135 | 135 |
136 // Quantifiers | 136 // Quantifiers |
137 '*', | 137 '*', |
138 '+', | 138 '+', |
139 '?', | 139 '?', |
140 '{', | 140 '{', |
141 '}', | 141 '}', |
142 }; | 142 }; |
143 | 143 |
144 // Anchor regex at start of path. | 144 // Anchor regex at start of path. |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 sandbox_data = [sandbox_data | 338 sandbox_data = [sandbox_data |
339 stringByReplacingOccurrencesOfString:@";NACL" | 339 stringByReplacingOccurrencesOfString:@";NACL" |
340 withString:@""]; | 340 withString:@""]; |
341 } | 341 } |
342 | 342 |
343 if (!allowed_dir.empty()) { | 343 if (!allowed_dir.empty()) { |
344 // The sandbox only understands "real" paths. This resolving step is | 344 // The sandbox only understands "real" paths. This resolving step is |
345 // needed so the caller doesn't need to worry about things like /var | 345 // needed so the caller doesn't need to worry about things like /var |
346 // being a link to /private/var (like in the paths CreateNewTempDirectory() | 346 // being a link to /private/var (like in the paths CreateNewTempDirectory() |
347 // returns). | 347 // returns). |
348 FilePath allowed_dir_absolute(allowed_dir); | 348 FilePath allowed_dir_canonical(allowed_dir); |
349 if (!file_util::AbsolutePath(&allowed_dir_absolute)) { | 349 GetCanonicalSandboxPath(&allowed_dir_canonical); |
350 PLOG(FATAL) << "Failed to resolve absolute path"; | |
351 return false; | |
352 } | |
353 | 350 |
354 std::string allowed_dir_escaped; | 351 std::string allowed_dir_escaped; |
355 if (!QuoteStringForRegex(allowed_dir_absolute.value(), | 352 if (!QuoteStringForRegex(allowed_dir_canonical.value(), |
356 &allowed_dir_escaped)) { | 353 &allowed_dir_escaped)) { |
357 LOG(FATAL) << "Regex string quoting failed " << allowed_dir.value(); | 354 LOG(FATAL) << "Regex string quoting failed " << allowed_dir.value(); |
358 return false; | 355 return false; |
359 } | 356 } |
360 NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString( | 357 NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString( |
361 allowed_dir_escaped.c_str()); | 358 allowed_dir_escaped.c_str()); |
362 sandbox_data = [sandbox_data | 359 sandbox_data = [sandbox_data |
363 stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS" | 360 stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS" |
364 withString:@""]; | 361 withString:@""]; |
365 sandbox_data = [sandbox_data | 362 sandbox_data = [sandbox_data |
(...skipping 11 matching lines...) Expand all Loading... |
377 sandbox_data = [sandbox_data | 374 sandbox_data = [sandbox_data |
378 stringByReplacingOccurrencesOfString:@";10.6_ONLY" | 375 stringByReplacingOccurrencesOfString:@";10.6_ONLY" |
379 withString:@""]; | 376 withString:@""]; |
380 // Splice the path of the user's home directory into the sandbox profile | 377 // Splice the path of the user's home directory into the sandbox profile |
381 // (see renderer.sb for details). | 378 // (see renderer.sb for details). |
382 // This code is in the 10.6-only block because the sandbox syntax we use | 379 // This code is in the 10.6-only block because the sandbox syntax we use |
383 // for this "subdir" is only supported on 10.6. | 380 // for this "subdir" is only supported on 10.6. |
384 // If we ever need this on pre-10.6 OSs then we'll have to rethink the | 381 // If we ever need this on pre-10.6 OSs then we'll have to rethink the |
385 // surrounding sandbox syntax. | 382 // surrounding sandbox syntax. |
386 std::string home_dir = base::SysNSStringToUTF8(NSHomeDirectory()); | 383 std::string home_dir = base::SysNSStringToUTF8(NSHomeDirectory()); |
| 384 |
| 385 FilePath home_dir_canonical(home_dir); |
| 386 GetCanonicalSandboxPath(&home_dir_canonical); |
| 387 |
387 std::string home_dir_escaped; | 388 std::string home_dir_escaped; |
388 if (!QuotePlainString(home_dir, &home_dir_escaped)) { | 389 if (!QuotePlainString(home_dir_canonical.value(), &home_dir_escaped)) { |
389 LOG(FATAL) << "Sandbox string quoting failed"; | 390 LOG(FATAL) << "Sandbox string quoting failed"; |
390 return false; | 391 return false; |
391 } | 392 } |
392 NSString* home_dir_escaped_ns = base::SysUTF8ToNSString(home_dir_escaped); | 393 NSString* home_dir_escaped_ns = base::SysUTF8ToNSString(home_dir_escaped); |
393 sandbox_data = [sandbox_data | 394 sandbox_data = [sandbox_data |
394 stringByReplacingOccurrencesOfString:@"USER_HOMEDIR" | 395 stringByReplacingOccurrencesOfString:@"USER_HOMEDIR" |
395 withString:home_dir_escaped_ns]; | 396 withString:home_dir_escaped_ns]; |
396 } else if (major_version == 10 && minor_version < 6) { | 397 } else if (major_version == 10 && minor_version < 6) { |
397 // Sandbox rules only for versions before 10.6. | 398 // Sandbox rules only for versions before 10.6. |
398 sandbox_data = [sandbox_data | 399 sandbox_data = [sandbox_data |
399 stringByReplacingOccurrencesOfString:@";BEFORE_10.6" | 400 stringByReplacingOccurrencesOfString:@";BEFORE_10.6" |
400 withString:@""]; | 401 withString:@""]; |
401 } | 402 } |
402 | 403 |
403 char* error_buff = NULL; | 404 char* error_buff = NULL; |
404 int error = sandbox_init([sandbox_data UTF8String], 0, &error_buff); | 405 int error = sandbox_init([sandbox_data UTF8String], 0, &error_buff); |
405 bool success = (error == 0 && error_buff == NULL); | 406 bool success = (error == 0 && error_buff == NULL); |
406 LOG_IF(FATAL, !success) << "Failed to initialize sandbox: " | 407 LOG_IF(FATAL, !success) << "Failed to initialize sandbox: " |
407 << error | 408 << error |
408 << " " | 409 << " " |
409 << error_buff; | 410 << error_buff; |
410 sandbox_free_error(error_buff); | 411 sandbox_free_error(error_buff); |
411 return success; | 412 return success; |
412 } | 413 } |
413 | 414 |
| 415 void GetCanonicalSandboxPath(FilePath* path) { |
| 416 int fd = HANDLE_EINTR(open(path->value().c_str(), O_RDONLY)); |
| 417 if (fd < 0) { |
| 418 PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " |
| 419 << path->value(); |
| 420 return; |
| 421 } |
| 422 file_util::ScopedFD file_closer(&fd); |
| 423 |
| 424 FilePath::CharType canonical_path[MAXPATHLEN]; |
| 425 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { |
| 426 PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " |
| 427 << path->value(); |
| 428 return; |
| 429 } |
| 430 |
| 431 *path = FilePath(canonical_path); |
| 432 } |
| 433 |
414 } // namespace sandbox | 434 } // namespace sandbox |
OLD | NEW |