OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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" { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 CGImageSourceCreateWithData((CFDataRef)data, | 235 CGImageSourceCreateWithData((CFDataRef)data, |
236 NULL)); | 236 NULL)); |
237 CGImageSourceGetStatus(img); | 237 CGImageSourceGetStatus(img); |
238 } | 238 } |
239 | 239 |
240 { // Native Client access to /dev/random. | 240 { // Native Client access to /dev/random. |
241 GetUrandomFD(); | 241 GetUrandomFD(); |
242 } | 242 } |
243 } | 243 } |
244 | 244 |
| 245 // Build the Sandbox command necessary to allow access to a named directory |
| 246 // indicated by |allowed_dir|. |
| 247 // returns a string containing the sandbox profile commands necesary to allow |
| 248 // access to that directory or nil if an error occured. |
| 249 NSString* BuildAllowDirectoryAccessSandboxString(const FilePath& allowed_dir) { |
| 250 // A whitelist is used to determine which directories can be statted |
| 251 // This means that in the case of an /a/b/c/d/ directory, we may be able to |
| 252 // stat the leaf directory, but not it's parent. |
| 253 // The extension code in Chrome calls realpath() which fails if it can't call |
| 254 // stat() on one of the parent directories in the path. |
| 255 // The solution to this is to allow statting the parent directories themselves |
| 256 // but not their contents. We need to add a separate rule for each parent |
| 257 // directory. |
| 258 |
| 259 // The sandbox only understands "real" paths. This resolving step is |
| 260 // needed so the caller doesn't need to worry about things like /var |
| 261 // being a link to /private/var (like in the paths CreateNewTempDirectory() |
| 262 // returns). |
| 263 FilePath allowed_dir_canonical(allowed_dir); |
| 264 GetCanonicalSandboxPath(&allowed_dir_canonical); |
| 265 |
| 266 // Collect a list of all parent directories. |
| 267 FilePath last_path = allowed_dir_canonical; |
| 268 std::vector<FilePath> subpaths; |
| 269 for (FilePath path = allowed_dir_canonical.DirName(); |
| 270 path.value() != last_path.value(); |
| 271 path = path.DirName()) { |
| 272 subpaths.push_back(path); |
| 273 last_path = path; |
| 274 } |
| 275 |
| 276 // Iterate through all parents and allow stat() on them explicitly. |
| 277 NSString* sandbox_command = @"(allow file-read-metadata "; |
| 278 for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin(); |
| 279 i != subpaths.rend(); |
| 280 ++i) { |
| 281 std::string subdir_escaped; |
| 282 if (!QuotePlainString(i->value(), &subdir_escaped)) { |
| 283 LOG(FATAL) << "String quoting failed " << i->value(); |
| 284 return nil; |
| 285 } |
| 286 |
| 287 NSString* subdir_escaped_ns = |
| 288 base::SysUTF8ToNSString(subdir_escaped.c_str()); |
| 289 sandbox_command = |
| 290 [sandbox_command stringByAppendingFormat:@"(literal \"%@\")", |
| 291 subdir_escaped_ns]; |
| 292 } |
| 293 |
| 294 // Finally append the leaf directory. Unlike it's parents (for which only |
| 295 // stat() should be allowed), the leaf directory needs full access. |
| 296 sandbox_command = |
| 297 [sandbox_command |
| 298 stringByAppendingString:@") (allow file-read* file-write* "]; |
| 299 |
| 300 std::string allowed_dir_escaped; |
| 301 if (!QuoteStringForRegex(allowed_dir_canonical.value(), |
| 302 &allowed_dir_escaped)) { |
| 303 LOG(FATAL) << "Regex string quoting failed " |
| 304 << allowed_dir_canonical.value(); |
| 305 return nil; |
| 306 } |
| 307 |
| 308 NSString* allowed_dir_canonical_ns = |
| 309 base::SysUTF8ToNSString(allowed_dir_escaped.c_str()); |
| 310 sandbox_command = |
| 311 [sandbox_command stringByAppendingFormat:@"(regex #\"%@\") )", |
| 312 allowed_dir_canonical_ns]; |
| 313 |
| 314 return sandbox_command; |
| 315 } |
| 316 |
245 // Turns on the OS X sandbox for this process. | 317 // Turns on the OS X sandbox for this process. |
246 bool EnableSandbox(SandboxProcessType sandbox_type, | 318 bool EnableSandbox(SandboxProcessType sandbox_type, |
247 const FilePath& allowed_dir) { | 319 const FilePath& allowed_dir) { |
248 // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being | 320 // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being |
249 // passed in. | 321 // passed in. |
250 if (sandbox_type != SANDBOX_TYPE_UTILITY) { | 322 if (sandbox_type != SANDBOX_TYPE_UTILITY) { |
251 DCHECK(allowed_dir.empty()) | 323 DCHECK(allowed_dir.empty()) |
252 << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter."; | 324 << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter."; |
253 } | 325 } |
254 // We use a custom sandbox definition file to lock things down as | 326 // We use a custom sandbox definition file to lock things down as |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 sandbox_data = [sandbox_data | 406 sandbox_data = [sandbox_data |
335 stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING" | 407 stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING" |
336 withString:@"(with no-log)"]; | 408 withString:@"(with no-log)"]; |
337 } else { | 409 } else { |
338 sandbox_data = [sandbox_data | 410 sandbox_data = [sandbox_data |
339 stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING" | 411 stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING" |
340 withString:@""]; | 412 withString:@""]; |
341 } | 413 } |
342 | 414 |
343 if (!allowed_dir.empty()) { | 415 if (!allowed_dir.empty()) { |
344 // The sandbox only understands "real" paths. This resolving step is | 416 NSString* allowed_dir_sandbox_command = |
345 // needed so the caller doesn't need to worry about things like /var | 417 BuildAllowDirectoryAccessSandboxString(allowed_dir); |
346 // being a link to /private/var (like in the paths CreateNewTempDirectory() | |
347 // returns). | |
348 FilePath allowed_dir_canonical(allowed_dir); | |
349 GetCanonicalSandboxPath(&allowed_dir_canonical); | |
350 | 418 |
351 std::string allowed_dir_escaped; | 419 if (allowed_dir_sandbox_command) { // May be nil if function fails. |
352 if (!QuoteStringForRegex(allowed_dir_canonical.value(), | 420 sandbox_data = [sandbox_data |
353 &allowed_dir_escaped)) { | 421 stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS" |
354 LOG(FATAL) << "Regex string quoting failed " << allowed_dir.value(); | 422 withString:allowed_dir_sandbox_command]; |
355 return false; | |
356 } | 423 } |
357 NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString( | |
358 allowed_dir_escaped.c_str()); | |
359 sandbox_data = [sandbox_data | |
360 stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS" | |
361 withString:@""]; | |
362 sandbox_data = [sandbox_data | |
363 stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS" | |
364 withString:allowed_dir_escaped_ns]; | |
365 | |
366 } | 424 } |
367 | 425 |
368 if (snow_leopard_or_higher) { | 426 if (snow_leopard_or_higher) { |
369 // 10.6-only Sandbox rules. | 427 // 10.6-only Sandbox rules. |
370 sandbox_data = [sandbox_data | 428 sandbox_data = [sandbox_data |
371 stringByReplacingOccurrencesOfString:@";10.6_ONLY" | 429 stringByReplacingOccurrencesOfString:@";10.6_ONLY" |
372 withString:@""]; | 430 withString:@""]; |
373 // Splice the path of the user's home directory into the sandbox profile | 431 // Splice the path of the user's home directory into the sandbox profile |
374 // (see renderer.sb for details). | 432 // (see renderer.sb for details). |
375 // This code is in the 10.6-only block because the sandbox syntax we use | 433 // This code is in the 10.6-only block because the sandbox syntax we use |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { | 479 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { |
422 PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " | 480 PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " |
423 << path->value(); | 481 << path->value(); |
424 return; | 482 return; |
425 } | 483 } |
426 | 484 |
427 *path = FilePath(canonical_path); | 485 *path = FilePath(canonical_path); |
428 } | 486 } |
429 | 487 |
430 } // namespace sandbox | 488 } // namespace sandbox |
OLD | NEW |