OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/mac_util.h" | 19 #include "base/mac/mac_util.h" |
20 #include "base/rand_util_c.h" | 20 #include "base/rand_util_c.h" |
21 #include "base/mac/scoped_cftyperef.h" | 21 #include "base/mac/scoped_cftyperef.h" |
22 #include "base/mac/scoped_nsautorelease_pool.h" | 22 #include "base/mac/scoped_nsautorelease_pool.h" |
23 #include "base/string16.h" | 23 #include "base/string16.h" |
| 24 #include "base/string_piece.h" |
24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
25 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
26 #include "base/sys_info.h" | 27 #include "base/sys_info.h" |
27 #include "base/sys_string_conversions.h" | 28 #include "base/sys_string_conversions.h" |
28 #include "base/utf_string_conversions.h" | 29 #include "base/utf_string_conversions.h" |
29 #include "content/common/chrome_application_mac.h" | 30 #include "content/common/chrome_application_mac.h" |
| 31 #include "content/public/common/content_client.h" |
30 #include "content/public/common/content_switches.h" | 32 #include "content/public/common/content_switches.h" |
| 33 #include "grit/content_resources.h" |
31 #include "unicode/uchar.h" | 34 #include "unicode/uchar.h" |
32 #include "ui/gfx/gl/gl_surface.h" | 35 #include "ui/gfx/gl/gl_surface.h" |
33 | 36 |
34 namespace { | 37 namespace { |
35 | 38 |
| 39 struct SandboxTypeToResourceIDMapping { |
| 40 content::SandboxType sandbox_type; |
| 41 int sandbox_profile_resource_id; |
| 42 }; |
| 43 |
| 44 // Mapping from sandbox process types to resource IDs containing the sandbox |
| 45 // profile for all process types known to content. |
| 46 SandboxTypeToResourceIDMapping kDefaultSandboxTypeToResourceIDMapping[] = { |
| 47 { content::SANDBOX_TYPE_RENDERER, IDR_RENDERER_SANDBOX_PROFILE }, |
| 48 { content::SANDBOX_TYPE_WORKER, IDR_WORKER_SANDBOX_PROFILE }, |
| 49 { content::SANDBOX_TYPE_UTILITY, IDR_UTILITY_SANDBOX_PROFILE }, |
| 50 { content::SANDBOX_TYPE_GPU, IDR_GPU_SANDBOX_PROFILE }, |
| 51 { content::SANDBOX_TYPE_PPAPI, IDR_PPAPI_SANDBOX_PROFILE }, |
| 52 }; |
| 53 |
| 54 COMPILE_ASSERT(arraysize(kDefaultSandboxTypeToResourceIDMapping) == \ |
| 55 size_t(content::SANDBOX_TYPE_AFTER_LAST_TYPE), \ |
| 56 sandbox_type_to_resource_id_mapping_incorrect); |
| 57 |
36 // Try to escape |c| as a "SingleEscapeCharacter" (\n, etc). If successful, | 58 // Try to escape |c| as a "SingleEscapeCharacter" (\n, etc). If successful, |
37 // returns true and appends the escape sequence to |dst|. | 59 // returns true and appends the escape sequence to |dst|. |
38 bool EscapeSingleChar(char c, std::string* dst) { | 60 bool EscapeSingleChar(char c, std::string* dst) { |
39 const char *append = NULL; | 61 const char *append = NULL; |
40 switch (c) { | 62 switch (c) { |
41 case '\b': | 63 case '\b': |
42 append = "\\b"; | 64 append = "\\b"; |
43 break; | 65 break; |
44 case '\f': | 66 case '\f': |
45 append = "\\f"; | 67 append = "\\f"; |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 | 205 |
184 // Warm up System APIs that empirically need to be accessed before the Sandbox | 206 // Warm up System APIs that empirically need to be accessed before the Sandbox |
185 // is turned on. | 207 // is turned on. |
186 // This method is layed out in blocks, each one containing a separate function | 208 // This method is layed out in blocks, each one containing a separate function |
187 // that needs to be warmed up. The OS version on which we found the need to | 209 // that needs to be warmed up. The OS version on which we found the need to |
188 // enable the function is also noted. | 210 // enable the function is also noted. |
189 // This function is tested on the following OS versions: | 211 // This function is tested on the following OS versions: |
190 // 10.5.6, 10.6.0 | 212 // 10.5.6, 10.6.0 |
191 | 213 |
192 // static | 214 // static |
193 void Sandbox::SandboxWarmup(SandboxProcessType sandbox_type) { | 215 void Sandbox::SandboxWarmup(int sandbox_type) { |
194 base::mac::ScopedNSAutoreleasePool scoped_pool; | 216 base::mac::ScopedNSAutoreleasePool scoped_pool; |
195 | 217 |
196 { // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6 | 218 { // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6 |
197 base::mac::ScopedCFTypeRef<CGColorSpaceRef> rgb_colorspace( | 219 base::mac::ScopedCFTypeRef<CGColorSpaceRef> rgb_colorspace( |
198 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); | 220 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); |
199 | 221 |
200 // Allocate a 1x1 image. | 222 // Allocate a 1x1 image. |
201 char data[4]; | 223 char data[4]; |
202 base::mac::ScopedCFTypeRef<CGContextRef> context( | 224 base::mac::ScopedCFTypeRef<CGContextRef> context( |
203 CGBitmapContextCreate(data, 1, 1, 8, 1 * 4, | 225 CGBitmapContextCreate(data, 1, 1, 8, 1 * 4, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 NULL)); | 262 NULL)); |
241 CGImageSourceGetStatus(img); | 263 CGImageSourceGetStatus(img); |
242 } | 264 } |
243 | 265 |
244 { | 266 { |
245 // Allow access to /dev/urandom. | 267 // Allow access to /dev/urandom. |
246 GetUrandomFD(); | 268 GetUrandomFD(); |
247 } | 269 } |
248 | 270 |
249 // Process-type dependent warm-up. | 271 // Process-type dependent warm-up. |
250 switch (sandbox_type) { | 272 if (sandbox_type == content::SANDBOX_TYPE_GPU) { |
251 case SANDBOX_TYPE_GPU: | 273 // Preload either the desktop GL or the osmesa so, depending on the |
252 { | 274 // --use-gl flag. |
253 // Preload either the desktop GL or the osmesa so, depending on the | 275 gfx::GLSurface::InitializeOneOff(); |
254 // --use-gl flag. | |
255 gfx::GLSurface::InitializeOneOff(); | |
256 } | |
257 break; | |
258 | |
259 default: | |
260 // To shut up a gcc warning. | |
261 break; | |
262 } | 276 } |
263 } | 277 } |
264 | 278 |
265 // static | 279 // static |
266 NSString* Sandbox::BuildAllowDirectoryAccessSandboxString( | 280 NSString* Sandbox::BuildAllowDirectoryAccessSandboxString( |
267 const FilePath& allowed_dir, | 281 const FilePath& allowed_dir, |
268 SandboxVariableSubstitions* substitutions) { | 282 SandboxVariableSubstitions* substitutions) { |
269 // A whitelist is used to determine which directories can be statted | 283 // A whitelist is used to determine which directories can be statted |
270 // This means that in the case of an /a/b/c/d/ directory, we may be able to | 284 // This means that in the case of an /a/b/c/d/ directory, we may be able to |
271 // stat the leaf directory, but not it's parent. | 285 // stat the leaf directory, but not it's parent. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 SandboxSubstring::REGEX); | 331 SandboxSubstring::REGEX); |
318 sandbox_command = | 332 sandbox_command = |
319 [sandbox_command | 333 [sandbox_command |
320 stringByAppendingString:@") (allow file-read* file-write*" | 334 stringByAppendingString:@") (allow file-read* file-write*" |
321 " (regex #\"@ALLOWED_DIR@\") )"]; | 335 " (regex #\"@ALLOWED_DIR@\") )"]; |
322 return sandbox_command; | 336 return sandbox_command; |
323 } | 337 } |
324 | 338 |
325 // Load the appropriate template for the given sandbox type. | 339 // Load the appropriate template for the given sandbox type. |
326 // Returns the template as an NSString or nil on error. | 340 // Returns the template as an NSString or nil on error. |
327 NSString* LoadSandboxTemplate(Sandbox::SandboxProcessType sandbox_type) { | 341 NSString* LoadSandboxTemplate(int sandbox_type) { |
328 // We use a custom sandbox definition file to lock things down as | 342 // We use a custom sandbox definition to lock things down as tightly as |
329 // tightly as possible. | 343 // possible. |
330 NSString* sandbox_config_filename = nil; | 344 int sandbox_profile_resource_id = -1; |
331 switch (sandbox_type) { | 345 |
332 case Sandbox::SANDBOX_TYPE_RENDERER: | 346 // Find resource id for sandbox profile to use for the specific sandbox type. |
333 sandbox_config_filename = @"renderer"; | 347 for (size_t i = 0; |
| 348 i < arraysize(kDefaultSandboxTypeToResourceIDMapping); |
| 349 ++i) { |
| 350 if (kDefaultSandboxTypeToResourceIDMapping[i].sandbox_type == |
| 351 sandbox_type) { |
| 352 sandbox_profile_resource_id = |
| 353 kDefaultSandboxTypeToResourceIDMapping[i].sandbox_profile_resource_id; |
334 break; | 354 break; |
335 case Sandbox::SANDBOX_TYPE_WORKER: | 355 } |
336 sandbox_config_filename = @"worker"; | 356 } |
337 break; | 357 if (sandbox_profile_resource_id == -1) { |
338 case Sandbox::SANDBOX_TYPE_UTILITY: | 358 // Check if the embedder knows about this sandbox process type. |
339 sandbox_config_filename = @"utility"; | 359 bool sandbox_type_found = |
340 break; | 360 content::GetContentClient()->GetSandboxProfileForSandboxType( |
341 case Sandbox::SANDBOX_TYPE_NACL_LOADER: | 361 sandbox_type, &sandbox_profile_resource_id); |
342 // The Native Client loader is used for safeguarding the user's | 362 CHECK(sandbox_type_found) << "Unknown sandbox type " << sandbox_type; |
343 // untrusted code within Native Client. | |
344 sandbox_config_filename = @"nacl_loader"; | |
345 break; | |
346 case Sandbox::SANDBOX_TYPE_GPU: | |
347 sandbox_config_filename = @"gpu"; | |
348 break; | |
349 case Sandbox::SANDBOX_TYPE_PPAPI: | |
350 sandbox_config_filename = @"ppapi"; | |
351 break; | |
352 default: | |
353 NOTREACHED(); | |
354 return nil; | |
355 } | 363 } |
356 | 364 |
357 // Read in the sandbox profile and the common prefix file. | 365 base::StringPiece sandbox_definition = |
358 NSString* common_sandbox_prefix_path = | 366 content::GetContentClient()->GetDataResource(sandbox_profile_resource_id); |
359 [base::mac::MainAppBundle() pathForResource:@"common" | 367 if (sandbox_definition.empty()) { |
360 ofType:@"sb"]; | 368 LOG(FATAL) << "Failed to load the sandbox profile (resource id " |
361 NSString* common_sandbox_prefix_data = | 369 << sandbox_profile_resource_id << ")"; |
362 [NSString stringWithContentsOfFile:common_sandbox_prefix_path | |
363 encoding:NSUTF8StringEncoding | |
364 error:NULL]; | |
365 | |
366 if (!common_sandbox_prefix_data) { | |
367 DLOG(FATAL) << "Failed to find the sandbox profile on disk " | |
368 << [common_sandbox_prefix_path fileSystemRepresentation]; | |
369 return nil; | 370 return nil; |
370 } | 371 } |
371 | 372 |
372 NSString* sandbox_profile_path = | 373 base::StringPiece common_sandbox_definition = |
373 [base::mac::MainAppBundle() pathForResource:sandbox_config_filename | 374 content::GetContentClient()->GetDataResource(IDR_COMMON_SANDBOX_PROFILE); |
374 ofType:@"sb"]; | 375 if (common_sandbox_definition.empty()) { |
375 NSString* sandbox_data = | 376 LOG(FATAL) << "Failed to load the common sandbox profile"; |
376 [NSString stringWithContentsOfFile:sandbox_profile_path | |
377 encoding:NSUTF8StringEncoding | |
378 error:NULL]; | |
379 | |
380 if (!sandbox_data) { | |
381 DLOG(FATAL) << "Failed to find the sandbox profile on disk " | |
382 << [sandbox_profile_path fileSystemRepresentation]; | |
383 return nil; | 377 return nil; |
384 } | 378 } |
385 | 379 |
| 380 NSString* common_sandbox_prefix_data = |
| 381 [[NSString alloc] initWithBytes:common_sandbox_definition.data() |
| 382 length:common_sandbox_definition.length() |
| 383 encoding:NSUTF8StringEncoding]; |
| 384 |
| 385 NSString* sandbox_data = |
| 386 [[NSString alloc] initWithBytes:sandbox_definition.data() |
| 387 length:sandbox_definition.length() |
| 388 encoding:NSUTF8StringEncoding]; |
| 389 |
386 // Prefix sandbox_data with common_sandbox_prefix_data. | 390 // Prefix sandbox_data with common_sandbox_prefix_data. |
387 return [common_sandbox_prefix_data stringByAppendingString:sandbox_data]; | 391 return [common_sandbox_prefix_data stringByAppendingString:sandbox_data]; |
388 } | 392 } |
389 | 393 |
390 // static | 394 // static |
391 bool Sandbox::PostProcessSandboxProfile( | 395 bool Sandbox::PostProcessSandboxProfile( |
392 NSString* sandbox_template, | 396 NSString* sandbox_template, |
393 NSArray* comments_to_remove, | 397 NSArray* comments_to_remove, |
394 SandboxVariableSubstitions& substitutions, | 398 SandboxVariableSubstitions& substitutions, |
395 std::string *final_sandbox_profile_str) { | 399 std::string *final_sandbox_profile_str) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 ++it) { | 456 ++it) { |
453 final_sandbox_profile_str->append(*it); | 457 final_sandbox_profile_str->append(*it); |
454 } | 458 } |
455 return true; | 459 return true; |
456 } | 460 } |
457 | 461 |
458 | 462 |
459 // Turns on the OS X sandbox for this process. | 463 // Turns on the OS X sandbox for this process. |
460 | 464 |
461 // static | 465 // static |
462 bool Sandbox::EnableSandbox(SandboxProcessType sandbox_type, | 466 bool Sandbox::EnableSandbox(int sandbox_type, |
463 const FilePath& allowed_dir) { | 467 const FilePath& allowed_dir) { |
464 // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being | 468 // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being |
465 // passed in. | 469 // passed in. |
466 if (sandbox_type != SANDBOX_TYPE_UTILITY) { | 470 if (sandbox_type < content::SANDBOX_TYPE_AFTER_LAST_TYPE && |
| 471 sandbox_type != content::SANDBOX_TYPE_UTILITY) { |
467 DCHECK(allowed_dir.empty()) | 472 DCHECK(allowed_dir.empty()) |
468 << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter."; | 473 << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter."; |
469 } | 474 } |
470 | 475 |
471 NSString* sandbox_data = LoadSandboxTemplate(sandbox_type); | 476 NSString* sandbox_data = LoadSandboxTemplate(sandbox_type); |
472 if (!sandbox_data) { | 477 if (!sandbox_data) { |
473 return false; | 478 return false; |
474 } | 479 } |
475 | 480 |
476 SandboxVariableSubstitions substitutions; | 481 SandboxVariableSubstitions substitutions; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { | 575 if (HANDLE_EINTR(fcntl(fd, F_GETPATH, canonical_path)) != 0) { |
571 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " | 576 DPLOG(FATAL) << "GetCanonicalSandboxPath() failed for: " |
572 << path->value(); | 577 << path->value(); |
573 return; | 578 return; |
574 } | 579 } |
575 | 580 |
576 *path = FilePath(canonical_path); | 581 *path = FilePath(canonical_path); |
577 } | 582 } |
578 | 583 |
579 } // namespace sandbox | 584 } // namespace sandbox |
OLD | NEW |