diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-25 20:55:24 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-25 20:55:24 +0000 |
commit | dbd82584da433118de55fb3319be12c4c3536cf2 (patch) | |
tree | bba6762062c6bff54dce8cadcb2a7d19a7ea19eb /content/common | |
parent | 0cc75fe16b6e272176ee8db613ceef0990825bcf (diff) | |
download | chromium_src-dbd82584da433118de55fb3319be12c4c3536cf2.zip chromium_src-dbd82584da433118de55fb3319be12c4c3536cf2.tar.gz chromium_src-dbd82584da433118de55fb3319be12c4c3536cf2.tar.bz2 |
Load mac sandbox definitions from resources instead of the bundle.
Also, move all mac sandbox unittests to content
BUG=90443
TEST=content_unittests
Review URL: http://codereview.chromium.org/8589001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/sandbox_init_mac.cc | 61 | ||||
-rw-r--r-- | content/common/sandbox_init_mac.h | 22 | ||||
-rw-r--r-- | content/common/sandbox_mac.h | 42 | ||||
-rw-r--r-- | content/common/sandbox_mac.mm | 135 | ||||
-rw-r--r-- | content/common/sandbox_mac_fontloading_unittest.mm | 2 | ||||
-rw-r--r-- | content/common/sandbox_mac_unittest_helper.h | 10 | ||||
-rw-r--r-- | content/common/sandbox_mac_unittest_helper.mm | 15 |
7 files changed, 156 insertions, 131 deletions
diff --git a/content/common/sandbox_init_mac.cc b/content/common/sandbox_init_mac.cc index 86cf9e6..7fd288d 100644 --- a/content/common/sandbox_init_mac.cc +++ b/content/common/sandbox_init_mac.cc @@ -12,21 +12,34 @@ namespace content { -bool InitializeSandbox() { - using sandbox::Sandbox; +bool InitializeSandbox(int sandbox_type, const FilePath& allowed_dir) { + // Warm up APIs before turning on the sandbox. + sandbox::Sandbox::SandboxWarmup(sandbox_type); + + // Actually sandbox the process. + return sandbox::Sandbox::EnableSandbox(sandbox_type, allowed_dir); +} + +// Fill in |sandbox_type| and |allowed_dir| based on the command line, returns +// false if the current process type doesn't need to be sandboxed or if the +// sandbox was disabled from the command line. +bool GetSandboxTypeFromCommandLine(int* sandbox_type, + FilePath* allowed_dir) { + DCHECK(sandbox_type); + DCHECK(allowed_dir); + + *sandbox_type = -1; + *allowed_dir = FilePath(); // Empty by default. const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kNoSandbox)) - return true; - - Sandbox::SandboxProcessType sandbox_process_type; - FilePath allowed_dir; // Empty by default. + return false; std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); if (process_type.empty()) { // Browser process isn't sandboxed. - return true; + return false; } else if (process_type == switches::kRendererProcess) { if (!command_line.HasSwitch(switches::kDisable3DAPIs) && !command_line.HasSwitch(switches::kDisableExperimentalWebGL) && @@ -34,41 +47,41 @@ bool InitializeSandbox() { // TODO(kbr): this check seems to be necessary only on this // platform because the sandbox is initialized later. Remove // this once this flag is removed. - return true; + return false; } else { - sandbox_process_type = Sandbox::SANDBOX_TYPE_RENDERER; + *sandbox_type = SANDBOX_TYPE_RENDERER; } } else if (process_type == switches::kUtilityProcess) { // Utility process sandbox. - sandbox_process_type = Sandbox::SANDBOX_TYPE_UTILITY; - allowed_dir = + *sandbox_type = SANDBOX_TYPE_UTILITY; + *allowed_dir = command_line.GetSwitchValuePath(switches::kUtilityProcessAllowedDir); } else if (process_type == switches::kWorkerProcess) { // Worker process sandbox. - sandbox_process_type = Sandbox::SANDBOX_TYPE_WORKER; - } else if (process_type == switches::kNaClLoaderProcess) { - // Native Client sel_ldr (user untrusted code) sandbox. - sandbox_process_type = Sandbox::SANDBOX_TYPE_NACL_LOADER; + *sandbox_type = SANDBOX_TYPE_WORKER; } else if (process_type == switches::kGpuProcess) { - sandbox_process_type = Sandbox::SANDBOX_TYPE_GPU; + *sandbox_type = SANDBOX_TYPE_GPU; } else if ((process_type == switches::kPluginProcess) || (process_type == switches::kServiceProcess) || (process_type == switches::kPpapiBrokerProcess)) { - return true; + return false; } else if (process_type == switches::kPpapiPluginProcess) { - sandbox_process_type = Sandbox::SANDBOX_TYPE_PPAPI; + *sandbox_type = SANDBOX_TYPE_PPAPI; } else { // Failsafe: If you hit an unreached here, is your new process type in need // of sandboxing? NOTREACHED() << "Unknown process type " << process_type; - return true; + return false; } + return true; +} - // Warm up APIs before turning on the sandbox. - Sandbox::SandboxWarmup(sandbox_process_type); - - // Actually sandbox the process. - return Sandbox::EnableSandbox(sandbox_process_type, allowed_dir); +bool InitializeSandbox() { + int sandbox_type = 0; + FilePath allowed_dir; + if (!GetSandboxTypeFromCommandLine(&sandbox_type, &allowed_dir)) + return true; + return InitializeSandbox(sandbox_type, allowed_dir); } } // namespace content diff --git a/content/common/sandbox_init_mac.h b/content/common/sandbox_init_mac.h new file mode 100644 index 0000000..08512b5 --- /dev/null +++ b/content/common/sandbox_init_mac.h @@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_SANDBOX_INIT_MAC_H_ +#define CONTENT_COMMON_SANDBOX_INIT_MAC_H_ +#pragma once + +namespace content { + +// Initialize the sandbox for renderer, gpu, utility, worker, and plug-in +// processes, depending on the command line flags. Although The browser process +// is not sandboxed, this also needs to be called because it will initialize +// the broker code. +// Returns true if the sandbox was initialized succesfully, false if an error +// occurred. If process_type isn't one that needs sandboxing true is always +// returned. +bool InitializeSandbox(); + +} // namespace content + +#endif // CONTENT_COMMON_SANDBOX_INIT_MAC_H_ diff --git a/content/common/sandbox_mac.h b/content/common/sandbox_mac.h index 358c098..c9710c3 100644 --- a/content/common/sandbox_mac.h +++ b/content/common/sandbox_mac.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/hash_tables.h" #include "base/gtest_prod_util.h" +#include "content/public/common/sandbox_type_mac.h" class FilePath; @@ -57,44 +58,21 @@ class Sandbox { typedef base::hash_map<std::string, SandboxSubstring> SandboxVariableSubstitions; - enum SandboxProcessType { - SANDBOX_TYPE_FIRST_TYPE, // Placeholder to ease iteration. - - SANDBOX_TYPE_RENDERER = SANDBOX_TYPE_FIRST_TYPE, - - // The worker process uses the most restrictive sandbox which has almost - // *everything* locked down. Only a couple of /System/Library/ paths and - // some other very basic operations (e.g., reading metadata to allow - // following symlinks) are permitted. - SANDBOX_TYPE_WORKER, - - // Utility process is as restrictive as the worker process except full - // access is allowed to one configurable directory. - SANDBOX_TYPE_UTILITY, - - // Native Client sandbox for the user's untrusted code. - SANDBOX_TYPE_NACL_LOADER, - - // GPU process. - SANDBOX_TYPE_GPU, - - // The PPAPI plugin process. - SANDBOX_TYPE_PPAPI, - - SANDBOX_AFTER_TYPE_LAST_TYPE, // Placeholder to ease iteration. - }; - - // Warm up System APIs that empirically need to be accessed before the Sandbox - // is turned on. |sandbox_type| is the type of sandbox to warm up. - static void SandboxWarmup(SandboxProcessType sandbox_type); + // Warm up System APIs that empirically need to be accessed before the + // sandbox is turned on. |sandbox_type| is the type of sandbox to warm up. + // Valid |sandbox_type| values are defined by the enum SandboxType, or can be + // defined by the embedder via + // ContentClient::GetSandboxProfileForProcessType(). + static void SandboxWarmup(int sandbox_type); // Turns on the OS X sandbox for this process. - // |sandbox_type| - type of Sandbox to use. + // |sandbox_type| - type of Sandbox to use. See SandboxWarmup() for legal + // values. // |allowed_dir| - directory to allow access to, currently the only sandbox // profile that supports this is SANDBOX_TYPE_UTILITY . // // Returns true on success, false if an error occurred enabling the sandbox. - static bool EnableSandbox(SandboxProcessType sandbox_type, + static bool EnableSandbox(int sandbox_type, const FilePath& allowed_dir); diff --git a/content/common/sandbox_mac.mm b/content/common/sandbox_mac.mm index d1ab290..d58e001 100644 --- a/content/common/sandbox_mac.mm +++ b/content/common/sandbox_mac.mm @@ -21,18 +21,40 @@ extern "C" { #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "base/string16.h" +#include "base/string_piece.h" #include "base/string_util.h" #include "base/stringprintf.h" #include "base/sys_info.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" #include "content/common/chrome_application_mac.h" +#include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "grit/content_resources.h" #include "unicode/uchar.h" #include "ui/gfx/gl/gl_surface.h" namespace { +struct SandboxTypeToResourceIDMapping { + content::SandboxType sandbox_type; + int sandbox_profile_resource_id; +}; + +// Mapping from sandbox process types to resource IDs containing the sandbox +// profile for all process types known to content. +SandboxTypeToResourceIDMapping kDefaultSandboxTypeToResourceIDMapping[] = { + { content::SANDBOX_TYPE_RENDERER, IDR_RENDERER_SANDBOX_PROFILE }, + { content::SANDBOX_TYPE_WORKER, IDR_WORKER_SANDBOX_PROFILE }, + { content::SANDBOX_TYPE_UTILITY, IDR_UTILITY_SANDBOX_PROFILE }, + { content::SANDBOX_TYPE_GPU, IDR_GPU_SANDBOX_PROFILE }, + { content::SANDBOX_TYPE_PPAPI, IDR_PPAPI_SANDBOX_PROFILE }, +}; + +COMPILE_ASSERT(arraysize(kDefaultSandboxTypeToResourceIDMapping) == \ + size_t(content::SANDBOX_TYPE_AFTER_LAST_TYPE), \ + sandbox_type_to_resource_id_mapping_incorrect); + // Try to escape |c| as a "SingleEscapeCharacter" (\n, etc). If successful, // returns true and appends the escape sequence to |dst|. bool EscapeSingleChar(char c, std::string* dst) { @@ -190,7 +212,7 @@ bool Sandbox::QuoteStringForRegex(const std::string& str_utf8, // 10.5.6, 10.6.0 // static -void Sandbox::SandboxWarmup(SandboxProcessType sandbox_type) { +void Sandbox::SandboxWarmup(int sandbox_type) { base::mac::ScopedNSAutoreleasePool scoped_pool; { // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6 @@ -247,18 +269,10 @@ void Sandbox::SandboxWarmup(SandboxProcessType sandbox_type) { } // Process-type dependent warm-up. - switch (sandbox_type) { - case SANDBOX_TYPE_GPU: - { - // Preload either the desktop GL or the osmesa so, depending on the - // --use-gl flag. - gfx::GLSurface::InitializeOneOff(); - } - break; - - default: - // To shut up a gcc warning. - break; + if (sandbox_type == content::SANDBOX_TYPE_GPU) { + // Preload either the desktop GL or the osmesa so, depending on the + // --use-gl flag. + gfx::GLSurface::InitializeOneOff(); } } @@ -324,65 +338,55 @@ NSString* Sandbox::BuildAllowDirectoryAccessSandboxString( // Load the appropriate template for the given sandbox type. // Returns the template as an NSString or nil on error. -NSString* LoadSandboxTemplate(Sandbox::SandboxProcessType sandbox_type) { - // We use a custom sandbox definition file to lock things down as - // tightly as possible. - NSString* sandbox_config_filename = nil; - switch (sandbox_type) { - case Sandbox::SANDBOX_TYPE_RENDERER: - sandbox_config_filename = @"renderer"; - break; - case Sandbox::SANDBOX_TYPE_WORKER: - sandbox_config_filename = @"worker"; - break; - case Sandbox::SANDBOX_TYPE_UTILITY: - sandbox_config_filename = @"utility"; - break; - case Sandbox::SANDBOX_TYPE_NACL_LOADER: - // The Native Client loader is used for safeguarding the user's - // untrusted code within Native Client. - sandbox_config_filename = @"nacl_loader"; - break; - case Sandbox::SANDBOX_TYPE_GPU: - sandbox_config_filename = @"gpu"; - break; - case Sandbox::SANDBOX_TYPE_PPAPI: - sandbox_config_filename = @"ppapi"; +NSString* LoadSandboxTemplate(int sandbox_type) { + // We use a custom sandbox definition to lock things down as tightly as + // possible. + int sandbox_profile_resource_id = -1; + + // Find resource id for sandbox profile to use for the specific sandbox type. + for (size_t i = 0; + i < arraysize(kDefaultSandboxTypeToResourceIDMapping); + ++i) { + if (kDefaultSandboxTypeToResourceIDMapping[i].sandbox_type == + sandbox_type) { + sandbox_profile_resource_id = + kDefaultSandboxTypeToResourceIDMapping[i].sandbox_profile_resource_id; break; - default: - NOTREACHED(); - return nil; + } + } + if (sandbox_profile_resource_id == -1) { + // Check if the embedder knows about this sandbox process type. + bool sandbox_type_found = + content::GetContentClient()->GetSandboxProfileForSandboxType( + sandbox_type, &sandbox_profile_resource_id); + CHECK(sandbox_type_found) << "Unknown sandbox type " << sandbox_type; } - // Read in the sandbox profile and the common prefix file. - NSString* common_sandbox_prefix_path = - [base::mac::MainAppBundle() pathForResource:@"common" - ofType:@"sb"]; - NSString* common_sandbox_prefix_data = - [NSString stringWithContentsOfFile:common_sandbox_prefix_path - encoding:NSUTF8StringEncoding - error:NULL]; - - if (!common_sandbox_prefix_data) { - DLOG(FATAL) << "Failed to find the sandbox profile on disk " - << [common_sandbox_prefix_path fileSystemRepresentation]; + base::StringPiece sandbox_definition = + content::GetContentClient()->GetDataResource(sandbox_profile_resource_id); + if (sandbox_definition.empty()) { + LOG(FATAL) << "Failed to load the sandbox profile (resource id " + << sandbox_profile_resource_id << ")"; return nil; } - NSString* sandbox_profile_path = - [base::mac::MainAppBundle() pathForResource:sandbox_config_filename - ofType:@"sb"]; - NSString* sandbox_data = - [NSString stringWithContentsOfFile:sandbox_profile_path - encoding:NSUTF8StringEncoding - error:NULL]; - - if (!sandbox_data) { - DLOG(FATAL) << "Failed to find the sandbox profile on disk " - << [sandbox_profile_path fileSystemRepresentation]; + base::StringPiece common_sandbox_definition = + content::GetContentClient()->GetDataResource(IDR_COMMON_SANDBOX_PROFILE); + if (common_sandbox_definition.empty()) { + LOG(FATAL) << "Failed to load the common sandbox profile"; return nil; } + NSString* common_sandbox_prefix_data = + [[NSString alloc] initWithBytes:common_sandbox_definition.data() + length:common_sandbox_definition.length() + encoding:NSUTF8StringEncoding]; + + NSString* sandbox_data = + [[NSString alloc] initWithBytes:sandbox_definition.data() + length:sandbox_definition.length() + encoding:NSUTF8StringEncoding]; + // Prefix sandbox_data with common_sandbox_prefix_data. return [common_sandbox_prefix_data stringByAppendingString:sandbox_data]; } @@ -459,11 +463,12 @@ bool Sandbox::PostProcessSandboxProfile( // Turns on the OS X sandbox for this process. // static -bool Sandbox::EnableSandbox(SandboxProcessType sandbox_type, +bool Sandbox::EnableSandbox(int sandbox_type, const FilePath& allowed_dir) { // Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being // passed in. - if (sandbox_type != SANDBOX_TYPE_UTILITY) { + if (sandbox_type < content::SANDBOX_TYPE_AFTER_LAST_TYPE && + sandbox_type != content::SANDBOX_TYPE_UTILITY) { DCHECK(allowed_dir.empty()) << "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter."; } diff --git a/content/common/sandbox_mac_fontloading_unittest.mm b/content/common/sandbox_mac_fontloading_unittest.mm index 911110f..7e7154f 100644 --- a/content/common/sandbox_mac_fontloading_unittest.mm +++ b/content/common/sandbox_mac_fontloading_unittest.mm @@ -121,7 +121,7 @@ TEST_F(MacSandboxTest, FontLoadingTest) { file_util::WriteFileDescriptor(fileno(temp_file), static_cast<const char *>(font_data.memory()), font_data_size); - ASSERT_TRUE(RunTestInSandbox(Sandbox::SANDBOX_TYPE_RENDERER, + ASSERT_TRUE(RunTestInSandbox(content::SANDBOX_TYPE_RENDERER, "FontLoadingTestCase", temp_file_path.value().c_str())); temp_file_closer.reset(); ASSERT_TRUE(file_util::Delete(temp_file_path, false)); diff --git a/content/common/sandbox_mac_unittest_helper.h b/content/common/sandbox_mac_unittest_helper.h index 84c3221..4246c26 100644 --- a/content/common/sandbox_mac_unittest_helper.h +++ b/content/common/sandbox_mac_unittest_helper.h @@ -51,15 +51,19 @@ class MacSandboxTest : public base::MultiProcessTest { // required. // Returns true if the test passes, false if either of the functions in // the corresponding MacSandboxTestCase return false. - bool RunTestInSandbox(sandbox::Sandbox::SandboxProcessType sandbox_type, + bool RunTestInSandbox(content::SandboxType sandbox_type, const char* test_name, const char* test_data); - // Runs the test specified by |test_name| in all the different sandbox types, - // one by one. + // Runs the test specified by |test_name| in all the different sandbox types + // known to content, one by one. // Returns true if the test passes, false if either of the functions in // the corresponding MacSandboxTestCase return false in any of the spawned // processes. + // + // DANGER DANGER DANGER: + // Additional sandbox types defined by the embedder (e.g. the NaCL sandbox) + // won't be covered by these tests. bool RunTestInAllSandboxTypes(const char* test_name, const char* test_data); }; diff --git a/content/common/sandbox_mac_unittest_helper.mm b/content/common/sandbox_mac_unittest_helper.mm index 89a29cd..5e52e2a 100644 --- a/content/common/sandbox_mac_unittest_helper.mm +++ b/content/common/sandbox_mac_unittest_helper.mm @@ -14,6 +14,7 @@ extern "C" { #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "content/common/sandbox_mac.h" +#include "content/test/test_content_client.h" #include "testing/multiprocess_func_list.h" using sandbox::Sandbox; @@ -54,11 +55,11 @@ bool MacSandboxTest::RunTestInAllSandboxTypes(const char* test_name, const char* test_data) { // Go through all the sandbox types, and run the test case in each of them // if one fails, abort. - for(int i = static_cast<int>(Sandbox::SANDBOX_TYPE_FIRST_TYPE); - i < Sandbox::SANDBOX_AFTER_TYPE_LAST_TYPE; + for(int i = static_cast<int>(content::SANDBOX_TYPE_FIRST_TYPE); + i < content::SANDBOX_TYPE_AFTER_LAST_TYPE; ++i) { - if (!RunTestInSandbox(static_cast<Sandbox::SandboxProcessType>(i), + if (!RunTestInSandbox(static_cast<content::SandboxType>(i), test_name, test_data)) { LOG(ERROR) << "Sandboxed test (" << test_name << ")" << "Failed in sandbox type " << i << @@ -69,7 +70,7 @@ bool MacSandboxTest::RunTestInAllSandboxTypes(const char* test_name, return true; } -bool MacSandboxTest::RunTestInSandbox(Sandbox::SandboxProcessType sandbox_type, +bool MacSandboxTest::RunTestInSandbox(content::SandboxType sandbox_type, const char* test_name, const char* test_data) { std::stringstream s; @@ -125,14 +126,16 @@ namespace { // Main function for driver process that enables the sandbox and runs test // code. MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) { + TestContentClient content_client; + content::SetContentClient(&content_client); // Extract parameters. char* sandbox_type_str = getenv(kSandboxTypeKey); if (!sandbox_type_str) { LOG(ERROR) << "Sandbox type not specified"; return -1; } - Sandbox::SandboxProcessType sandbox_type = - static_cast<Sandbox::SandboxProcessType>(atoi(sandbox_type_str)); + content::SandboxType sandbox_type = + static_cast<content::SandboxType>(atoi(sandbox_type_str)); char* sandbox_test_name = getenv(kSandboxTestNameKey); if (!sandbox_test_name) { LOG(ERROR) << "Sandbox test name not specified"; |