diff options
author | erg <erg@chromium.org> | 2015-07-28 11:46:08 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-28 18:46:41 +0000 |
commit | 38edd249fa0e6b5e1e1917e6d14077467e77439c (patch) | |
tree | fa4ac9b913ef8a8827a19b38f6d278e074af6313 | |
parent | 24a5806209d95faea058684b03a2d5f42c18ecae (diff) | |
download | chromium_src-38edd249fa0e6b5e1e1917e6d14077467e77439c.zip chromium_src-38edd249fa0e6b5e1e1917e6d14077467e77439c.tar.gz chromium_src-38edd249fa0e6b5e1e1917e6d14077467e77439c.tar.bz2 |
mandoline: Enable the sandbox on clipboard and tracing.
This modifies how we bring up child processes in the mandoline
shell. When sandboxing, we must raise the sandbox before we start any
threads on Linux. So we pass the path to the binary to run on the command
line in addition to passing it through mojo, so that we can pass that
file to the seccomp sandbox's file whitelist.
This is enough to get mojo:clipboard and mojo:tracing running in a
sandbox in --enable-multiprocess mode.
BUG=492524
Review URL: https://codereview.chromium.org/1239133004
Cr-Commit-Position: refs/heads/master@{#340734}
-rw-r--r-- | mandoline/app/core_services_initialization.cc | 8 | ||||
-rw-r--r-- | mandoline/app/desktop/BUILD.gn | 9 | ||||
-rw-r--r-- | mandoline/app/desktop/DEPS | 3 | ||||
-rw-r--r-- | mandoline/app/desktop/linux_sandbox.cc | 145 | ||||
-rw-r--r-- | mandoline/app/desktop/linux_sandbox.h | 52 | ||||
-rw-r--r-- | mandoline/app/desktop/main.cc | 32 | ||||
-rw-r--r-- | mojo/runner/BUILD.gn | 4 | ||||
-rw-r--r-- | mojo/runner/DEPS | 1 | ||||
-rw-r--r-- | mojo/runner/child_process_host.cc | 43 | ||||
-rw-r--r-- | mojo/runner/child_process_host.h | 19 | ||||
-rw-r--r-- | mojo/runner/child_process_host_unittest.cc | 2 | ||||
-rw-r--r-- | mojo/runner/in_process_native_runner.cc | 1 | ||||
-rw-r--r-- | mojo/runner/in_process_native_runner.h | 1 | ||||
-rw-r--r-- | mojo/runner/init.cc | 11 | ||||
-rw-r--r-- | mojo/runner/native_runner_unittest.cc | 1 | ||||
-rw-r--r-- | mojo/runner/out_of_process_native_runner.cc | 9 | ||||
-rw-r--r-- | mojo/runner/out_of_process_native_runner.h | 1 | ||||
-rw-r--r-- | mojo/runner/switches.cc | 14 | ||||
-rw-r--r-- | mojo/runner/switches.h | 2 | ||||
-rw-r--r-- | mojo/shell/application_manager.cc | 19 | ||||
-rw-r--r-- | mojo/shell/application_manager.h | 1 | ||||
-rw-r--r-- | mojo/shell/native_runner.h | 1 |
22 files changed, 337 insertions, 42 deletions
diff --git a/mandoline/app/core_services_initialization.cc b/mandoline/app/core_services_initialization.cc index 29e0bed..304fe1e 100644 --- a/mandoline/app/core_services_initialization.cc +++ b/mandoline/app/core_services_initialization.cc @@ -12,8 +12,8 @@ void InitCoreServicesForContext(mojo::runner::Context* context) { // TODO(erg): We should probably handle this differently; these could be // autogenerated from package manifests. mojo::shell::ApplicationManager* manager = context->application_manager(); - manager->RegisterApplicationPackageAlias(GURL("mojo:clipboard"), - GURL("mojo:core_services"), "Core"); + manager->RegisterApplicationPackageAlias( + GURL("mojo:clipboard"), GURL("mojo:core_services"), "Sandboxed Core"); manager->RegisterApplicationPackageAlias(GURL("mojo:filesystem"), GURL("mojo:core_services"), "Files"); #if !defined(OS_ANDROID) @@ -33,8 +33,8 @@ void InitCoreServicesForContext(mojo::runner::Context* context) { #endif manager->RegisterApplicationPackageAlias( GURL("mojo:surfaces_service"), GURL("mojo:core_services"), "Surfaces"); - manager->RegisterApplicationPackageAlias(GURL("mojo:tracing"), - GURL("mojo:core_services"), "Core"); + manager->RegisterApplicationPackageAlias( + GURL("mojo:tracing"), GURL("mojo:core_services"), "Sandboxed Core"); manager->RegisterApplicationPackageAlias(GURL("mojo:browser"), GURL("mojo:core_services"), "Core"); } diff --git a/mandoline/app/desktop/BUILD.gn b/mandoline/app/desktop/BUILD.gn index 6cdfcf2..200f7e1 100644 --- a/mandoline/app/desktop/BUILD.gn +++ b/mandoline/app/desktop/BUILD.gn @@ -25,6 +25,15 @@ executable("mandoline") { "//mojo/runner:lib", ] + if (is_linux && !is_android) { + sources += [ + "linux_sandbox.cc", + "linux_sandbox.h", + ] + + deps += [ "//sandbox/linux:sandbox" ] + } + data_deps = [ "//components/html_viewer", "//mandoline/services/core_services", diff --git a/mandoline/app/desktop/DEPS b/mandoline/app/desktop/DEPS new file mode 100644 index 0000000..ec69c8f --- /dev/null +++ b/mandoline/app/desktop/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+sandbox", +] diff --git a/mandoline/app/desktop/linux_sandbox.cc b/mandoline/app/desktop/linux_sandbox.cc new file mode 100644 index 0000000..732a99e --- /dev/null +++ b/mandoline/app/desktop/linux_sandbox.cc @@ -0,0 +1,145 @@ +// Copyright 2015 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. + +#include "mandoline/app/desktop/linux_sandbox.h" + +#include <fcntl.h> +#include <sys/syscall.h> + +#include "base/bind.h" +#include "base/debug/leak_annotations.h" +#include "base/posix/eintr_wrapper.h" +#include "base/rand_util.h" +#include "base/sys_info.h" +#include "sandbox/linux/bpf_dsl/policy.h" +#include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" +#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" +#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" +#include "sandbox/linux/services/credentials.h" +#include "sandbox/linux/services/namespace_sandbox.h" +#include "sandbox/linux/services/proc_util.h" + +using sandbox::syscall_broker::BrokerFilePermission; + +namespace mandoline { + +namespace { + +intptr_t SandboxSIGSYSHandler(const struct sandbox::arch_seccomp_data& args, + void* aux) { + RAW_CHECK(aux); + const sandbox::syscall_broker::BrokerProcess* broker_process = + static_cast<const sandbox::syscall_broker::BrokerProcess*>(aux); + switch (args.nr) { + case __NR_access: + return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), + static_cast<int>(args.args[1])); + case __NR_open: + return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), + static_cast<int>(args.args[1])); + case __NR_faccessat: + if (static_cast<int>(args.args[0]) == AT_FDCWD) { + return broker_process->Access( + reinterpret_cast<const char*>(args.args[1]), + static_cast<int>(args.args[2])); + } else { + return -EPERM; + } + case __NR_openat: + // Allow using openat() as open(). + if (static_cast<int>(args.args[0]) == AT_FDCWD) { + return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), + static_cast<int>(args.args[2])); + } else { + return -EPERM; + } + default: + RAW_CHECK(false); + return -ENOSYS; + } +} + +class SandboxPolicy : public sandbox::bpf_dsl::Policy { + public: + explicit SandboxPolicy(sandbox::syscall_broker::BrokerProcess* broker_process) + : broker_process_(broker_process) {} + ~SandboxPolicy() override {} + + // Overridden from sandbox::bpf_dsl::Policy: + sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override { + // This policy is only advisory/for noticing FS access for the moment. + switch (sysno) { + case __NR_access: + case __NR_open: + case __NR_faccessat: + case __NR_openat: + return sandbox::bpf_dsl::Trap(SandboxSIGSYSHandler, broker_process_); + } + + return sandbox::bpf_dsl::Allow(); + } + + private: + // Not owned. + const sandbox::syscall_broker::BrokerProcess* broker_process_; + DISALLOW_COPY_AND_ASSIGN(SandboxPolicy); +}; + +} // namespace + +LinuxSandbox::LinuxSandbox(const std::vector<BrokerFilePermission>& permissions) + : broker_(new sandbox::syscall_broker::BrokerProcess(EPERM, permissions)) { + broker_->Init( + base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities)); + policy_.reset(new SandboxPolicy(broker_.get())); +} + +LinuxSandbox::~LinuxSandbox() {} + +// static +std::vector<BrokerFilePermission> LinuxSandbox::GetPermissions() { + std::vector<BrokerFilePermission> permissions; + permissions.push_back(BrokerFilePermission::ReadOnly("/dev/urandom")); + permissions.push_back(BrokerFilePermission::ReadOnly("/etc/ld.so.cache")); + permissions.push_back(BrokerFilePermission::ReadOnlyRecursive("/lib/")); + permissions.push_back(BrokerFilePermission::ReadOnlyRecursive("/usr/lib/")); + return permissions; +} + +void LinuxSandbox::Warmup() { + proc_fd_ = sandbox::ProcUtil::OpenProc(); + warmed_up_ = true; +} + +void LinuxSandbox::EngageNamespaceSandbox() { + CHECK(warmed_up_); + CHECK_EQ(1, getpid()); + CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); + CHECK(sandbox::Credentials::MoveToNewUserNS()); + CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_.get())); + CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd_.get())); +} + +void LinuxSandbox::EngageSeccompSandbox() { + CHECK(warmed_up_); + sandbox::SandboxBPF sandbox(policy_.release()); + base::ScopedFD proc_fd(HANDLE_EINTR( + openat(proc_fd_.get(), ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); + CHECK(proc_fd.is_valid()); + sandbox.SetProcFd(proc_fd.Pass()); + CHECK( + sandbox.StartSandbox(sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED)) + << "Starting the process with a sandbox failed. Missing kernel support."; + + // The Broker is now bound to this process and should only be destroyed when + // the process exits or is killed. + ANNOTATE_LEAKING_OBJECT_PTR(broker_.release()); +} + +void LinuxSandbox::Seal() { + proc_fd_.reset(); +} + +} // namespace mandoline diff --git a/mandoline/app/desktop/linux_sandbox.h b/mandoline/app/desktop/linux_sandbox.h new file mode 100644 index 0000000..82cc084 --- /dev/null +++ b/mandoline/app/desktop/linux_sandbox.h @@ -0,0 +1,52 @@ +// Copyright 2015 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 MANDOLINE_APP_DESKTOP_LINUX_SANDBOX_H_ +#define MANDOLINE_APP_DESKTOP_LINUX_SANDBOX_H_ + +#include "base/files/scoped_file.h" +#include "sandbox/linux/bpf_dsl/bpf_dsl.h" +#include "sandbox/linux/bpf_dsl/policy.h" +#include "sandbox/linux/syscall_broker/broker_process.h" + +namespace mandoline { + +// Encapsulates all tasks related to raising the sandbox for mandoline. +class LinuxSandbox { + public: + explicit LinuxSandbox( + const std::vector<sandbox::syscall_broker::BrokerFilePermission>& + permissions); + ~LinuxSandbox(); + + // Returns a vector of file permissions needed to load libraries. + static std::vector<sandbox::syscall_broker::BrokerFilePermission> + GetPermissions(); + + // Grabs a file descriptor to /proc. + void Warmup(); + + // Puts the user in a new PID namespace. + void EngageNamespaceSandbox(); + + // Starts a broker process and sets up seccomp-bpf to delegate decisions to + // it. + void EngageSeccompSandbox(); + + // Performs the dropping of access to the outside world (drops the reference + // to /proc acquired in Warmup(). + void Seal(); + + private: + bool warmed_up_; + base::ScopedFD proc_fd_; + scoped_ptr<sandbox::syscall_broker::BrokerProcess> broker_; + scoped_ptr<sandbox::bpf_dsl::Policy> policy_; + + DISALLOW_COPY_AND_ASSIGN(LinuxSandbox); +}; + +} // namespace mandoline + +#endif // MANDOLINE_APP_DESKTOP_LINUX_SANDBOX_H_ diff --git a/mandoline/app/desktop/main.cc b/mandoline/app/desktop/main.cc index 8048baf..c01b36b 100644 --- a/mandoline/app/desktop/main.cc +++ b/mandoline/app/desktop/main.cc @@ -3,21 +3,47 @@ // found in the LICENSE file. #include "base/at_exit.h" +#include "base/bind.h" #include "base/command_line.h" +#include "base/files/file_path.h" #include "mandoline/app/desktop/launcher_process.h" #include "mojo/runner/child_process.h" #include "mojo/runner/init.h" +#include "mojo/runner/native_application_support.h" #include "mojo/runner/switches.h" +#include "mojo/shell/native_runner.h" + +#if defined(OS_LINUX) && !defined(OS_ANDROID) +#include "mandoline/app/desktop/linux_sandbox.h" +#endif int main(int argc, char** argv) { - base::AtExitManager at_exit; base::CommandLine::Init(argc, argv); + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + +#if defined(OS_LINUX) && !defined(OS_ANDROID) + using sandbox::syscall_broker::BrokerFilePermission; + scoped_ptr<mandoline::LinuxSandbox> sandbox; + if (command_line.HasSwitch(switches::kChildProcess) && + command_line.HasSwitch(switches::kEnableSandbox)) { + std::vector<BrokerFilePermission> permissions = + mandoline::LinuxSandbox::GetPermissions(); + permissions.push_back(BrokerFilePermission::ReadOnly( + command_line.GetSwitchValueNative(switches::kChildProcess))); + sandbox.reset(new mandoline::LinuxSandbox(permissions)); + sandbox->Warmup(); + sandbox->EngageNamespaceSandbox(); + sandbox->EngageSeccompSandbox(); + sandbox->Seal(); + } +#endif + + base::AtExitManager at_exit; mojo::runner::InitializeLogging(); mojo::runner::WaitForDebuggerIfNecessary(); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kChildProcess)) return mojo::runner::ChildProcessMain(); diff --git a/mojo/runner/BUILD.gn b/mojo/runner/BUILD.gn index fb652a0..f9aa64a 100644 --- a/mojo/runner/BUILD.gn +++ b/mojo/runner/BUILD.gn @@ -134,6 +134,10 @@ source_set("lib") { "//url", ] + if (is_linux && !is_android) { + deps += [ "//sandbox/linux:sandbox_services" ] + } + public_deps = [ ":switches", ] diff --git a/mojo/runner/DEPS b/mojo/runner/DEPS index 265b864..349288e 100644 --- a/mojo/runner/DEPS +++ b/mojo/runner/DEPS @@ -7,6 +7,7 @@ include_rules = [ "+components/view_manager/public", "+crypto", "+jni", + "+sandbox", "+third_party/mojo_services", "+ui", ] diff --git a/mojo/runner/child_process_host.cc b/mojo/runner/child_process_host.cc index dd3e1e0..d5d2104 100644 --- a/mojo/runner/child_process_host.cc +++ b/mojo/runner/child_process_host.cc @@ -22,13 +22,23 @@ #include "mojo/runner/switches.h" #include "mojo/runner/task_runners.h" +#if defined(OS_LINUX) && !defined(OS_ANDROID) +#include "sandbox/linux/services/namespace_sandbox.h" +#endif + namespace mojo { namespace runner { -ChildProcessHost::ChildProcessHost(Context* context, const std::string& name) - : context_(context), name_(name), channel_info_(nullptr) { +ChildProcessHost::ChildProcessHost(Context* context, + bool start_sandboxed, + const base::FilePath& app_path, + bool clean_app_path) + : context_(context), + start_sandboxed_(start_sandboxed), + app_path_(app_path), + clean_app_path_(clean_app_path), + channel_info_(nullptr) { platform_channel_ = platform_channel_pair_.PassServerHandle(); - DCHECK(!name.empty()); CHECK(platform_channel_.is_valid()); } @@ -66,15 +76,13 @@ int ChildProcessHost::Join() { } void ChildProcessHost::StartApp( - const String& app_path, - bool clean_app_path, InterfaceRequest<Application> application_request, const ChildController::StartAppCallback& on_app_complete) { DCHECK(controller_); on_app_complete_ = on_app_complete; controller_->StartApp( - app_path, clean_app_path, application_request.Pass(), + app_path_.AsUTF8Unsafe(), clean_app_path_, application_request.Pass(), base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this))); } @@ -99,8 +107,10 @@ bool ChildProcessHost::DoLaunch() { base::CommandLine::ForCurrentProcess(); base::CommandLine child_command_line(parent_command_line->GetProgram()); child_command_line.AppendArguments(*parent_command_line, false); - child_command_line.AppendSwitchASCII(switches::kApp, name_); - child_command_line.AppendSwitch(switches::kChildProcess); + child_command_line.AppendSwitchPath(switches::kChildProcess, app_path_); + + if (start_sandboxed_) + child_command_line.AppendSwitch(switches::kEnableSandbox); embedder::HandlePassingInformation handle_passing_info; platform_channel_pair_.PrepareToPassClientHandleToChildProcess( @@ -110,11 +120,26 @@ bool ChildProcessHost::DoLaunch() { #if defined(OS_WIN) options.handles_to_inherit = &handle_passing_info; #elif defined(OS_POSIX) + handle_passing_info.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO)); + handle_passing_info.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); + handle_passing_info.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO)); options.fds_to_remap = &handle_passing_info; #endif DVLOG(2) << "Launching child with command line: " << child_command_line.GetCommandLineString(); - child_process_ = base::LaunchProcess(child_command_line, options); +#if defined(OS_LINUX) && !defined(OS_ANDROID) + if (start_sandboxed_) { + child_process_ = + sandbox::NamespaceSandbox::LaunchProcess(child_command_line, options); + if (!child_process_.IsValid()) { + LOG(ERROR) << "Starting the process with a sandbox failed. Missing kernel" + << " support."; + return false; + } + } else +#endif + child_process_ = base::LaunchProcess(child_command_line, options); + if (!child_process_.IsValid()) return false; diff --git a/mojo/runner/child_process_host.h b/mojo/runner/child_process_host.h index cbc3d64..1875ede 100644 --- a/mojo/runner/child_process_host.h +++ b/mojo/runner/child_process_host.h @@ -5,6 +5,7 @@ #ifndef MOJO_RUNNER_CHILD_PROCESS_HOST_H_ #define MOJO_RUNNER_CHILD_PROCESS_HOST_H_ +#include "base/files/file_path.h" #include "base/macros.h" #include "base/process/process.h" #include "mojo/edk/embedder/channel_info_forward.h" @@ -30,8 +31,14 @@ class Context; // remained alive until the |on_app_complete| callback is called. class ChildProcessHost { public: - // |name| is just for debugging ease. - ChildProcessHost(Context* context, const std::string& name); + // |name| is just for debugging ease. We will spawn off a process so that it + // can be sandboxed if |start_sandboxed| is true. |app_path| is a path to the + // mojo application we wish to start. |clean_app_path| cleans up transient + // applications after execution. + ChildProcessHost(Context* context, + bool start_sandboxed, + const base::FilePath& app_path, + bool clean_app_path); virtual ~ChildProcessHost(); // |Start()|s the child process; calls |DidStart()| (on the thread on which @@ -47,9 +54,7 @@ class ChildProcessHost { int Join(); // See |ChildController|: - void StartApp(const String& app_path, - bool clean_app_path, - InterfaceRequest<Application> application_request, + void StartApp(InterfaceRequest<Application> application_request, const ChildController::StartAppCallback& on_app_complete); void ExitNow(int32_t exit_code); @@ -66,7 +71,9 @@ class ChildProcessHost { void DidCreateChannel(embedder::ChannelInfo* channel_info); Context* const context_; - const std::string name_; + bool start_sandboxed_; + const base::FilePath app_path_; + bool clean_app_path_; base::Process child_process_; embedder::PlatformChannelPair platform_channel_pair_; ChildControllerPtr controller_; diff --git a/mojo/runner/child_process_host_unittest.cc b/mojo/runner/child_process_host_unittest.cc index 8a90802..0443c46 100644 --- a/mojo/runner/child_process_host_unittest.cc +++ b/mojo/runner/child_process_host_unittest.cc @@ -21,7 +21,7 @@ namespace { class TestChildProcessHost : public ChildProcessHost { public: explicit TestChildProcessHost(Context* context) - : ChildProcessHost(context, "test") {} + : ChildProcessHost(context, false, base::FilePath(), false) {} ~TestChildProcessHost() override {} void DidStart(bool success) override { diff --git a/mojo/runner/in_process_native_runner.cc b/mojo/runner/in_process_native_runner.cc index 04321c0..36895af 100644 --- a/mojo/runner/in_process_native_runner.cc +++ b/mojo/runner/in_process_native_runner.cc @@ -32,6 +32,7 @@ InProcessNativeRunner::~InProcessNativeRunner() { void InProcessNativeRunner::Start( const base::FilePath& app_path, + bool start_sandboxed, shell::NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) { diff --git a/mojo/runner/in_process_native_runner.h b/mojo/runner/in_process_native_runner.h index 3e1e2e0..f5275a9 100644 --- a/mojo/runner/in_process_native_runner.h +++ b/mojo/runner/in_process_native_runner.h @@ -29,6 +29,7 @@ class InProcessNativeRunner : public shell::NativeRunner, // |NativeRunner| method: void Start(const base::FilePath& app_path, + bool start_sandboxed, shell::NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) override; diff --git a/mojo/runner/init.cc b/mojo/runner/init.cc index dc527c1..17d5c1b 100644 --- a/mojo/runner/init.cc +++ b/mojo/runner/init.cc @@ -7,6 +7,7 @@ #include "base/base_switches.h" #include "base/command_line.h" #include "base/debug/debugger.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/string_split.h" @@ -41,9 +42,13 @@ void WaitForDebuggerIfNecessary() { base::SplitString( command_line->GetSwitchValueASCII(switches::kWaitForDebugger), ',', &apps_to_debug); - std::string app = command_line->GetSwitchValueASCII(switches::kApp); - if (app.empty()) - app = "launcher"; // If we're not in a child process look for "launcher". + std::string app = "launcher"; + if (command_line->HasSwitch(switches::kChildProcess)) { + app = command_line->GetSwitchValuePath(switches::kChildProcess) + .BaseName() + .RemoveExtension() + .MaybeAsASCII(); + } if (apps_to_debug.empty() || ContainsValue(apps_to_debug, app)) { #if defined(OS_WIN) base::string16 appw = base::UTF8ToUTF16(app); diff --git a/mojo/runner/native_runner_unittest.cc b/mojo/runner/native_runner_unittest.cc index a237951..219600b 100644 --- a/mojo/runner/native_runner_unittest.cc +++ b/mojo/runner/native_runner_unittest.cc @@ -33,6 +33,7 @@ class TestNativeRunner : public shell::NativeRunner { base::MessageLoop::current()->Quit(); } void Start(const base::FilePath& app_path, + bool start_sandboxed, shell::NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) override { diff --git a/mojo/runner/out_of_process_native_runner.cc b/mojo/runner/out_of_process_native_runner.cc index 9623b79..a4e6850 100644 --- a/mojo/runner/out_of_process_native_runner.cc +++ b/mojo/runner/out_of_process_native_runner.cc @@ -30,6 +30,7 @@ OutOfProcessNativeRunner::~OutOfProcessNativeRunner() { void OutOfProcessNativeRunner::Start( const base::FilePath& app_path, + bool start_sandboxed, shell::NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) { @@ -38,14 +39,12 @@ void OutOfProcessNativeRunner::Start( DCHECK(app_completed_callback_.is_null()); app_completed_callback_ = app_completed_callback; - std::string name = app_path.BaseName().RemoveExtension().MaybeAsASCII(); - child_process_host_.reset(new ChildProcessHost(context_, name)); + bool clean_app_path = cleanup == shell::NativeApplicationCleanup::DELETE; + child_process_host_.reset(new ChildProcessHost(context_, start_sandboxed, + app_path, clean_app_path)); child_process_host_->Start(); - // TODO(vtl): |app_path.AsUTF8Unsafe()| is unsafe. child_process_host_->StartApp( - app_path.AsUTF8Unsafe(), - cleanup == shell::NativeApplicationCleanup::DELETE, application_request.Pass(), base::Bind(&OutOfProcessNativeRunner::AppCompleted, base::Unretained(this))); diff --git a/mojo/runner/out_of_process_native_runner.h b/mojo/runner/out_of_process_native_runner.h index d126c36..dccee56 100644 --- a/mojo/runner/out_of_process_native_runner.h +++ b/mojo/runner/out_of_process_native_runner.h @@ -27,6 +27,7 @@ class OutOfProcessNativeRunner : public shell::NativeRunner { // |NativeRunner| method: void Start(const base::FilePath& app_path, + bool start_sandboxed, shell::NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) override; diff --git a/mojo/runner/switches.cc b/mojo/runner/switches.cc index e6d0b4b..6b74ff9 100644 --- a/mojo/runner/switches.cc +++ b/mojo/runner/switches.cc @@ -8,22 +8,26 @@ namespace switches { -// Used just for debugging, to make it easier to attach debuggers. The actual -// app path that is used is sent over IPC. -const char kApp[] = "app"; - // Used internally by the main process to indicate that a new process should be -// a child process. Not for user use. +// a child process. Takes the absolute path to the mojo application to load as +// an argument. Not for user use. const char kChildProcess[] = "child-process"; // Comma separated list like: // text/html,mojo:html_viewer,application/bravo,https://abarth.com/bravo const char kContentHandlers[] = "content-handlers"; +// Used internally to delete a loaded application after we load it. Used for +// transient applications. Not for user use. +const char kDeleteAfterLoad[] = "delete-after-load"; + // Force dynamically loaded apps or services to be loaded irrespective of cache // instructions. const char kDisableCache[] = "disable-cache"; +// Enables the sandbox on this process. +const char kEnableSandbox[] = "enable-sandbox"; + // In multiprocess mode, force these apps to be loaded in the main process. // This is a comma-separated list of URLs. Example: // --force-in-process=mojo:native_viewport_service,mojo:network_service diff --git a/mojo/runner/switches.h b/mojo/runner/switches.h index 232c38a..1f84c9f 100644 --- a/mojo/runner/switches.h +++ b/mojo/runner/switches.h @@ -15,7 +15,9 @@ namespace switches { extern const char kApp[]; extern const char kChildProcess[]; extern const char kContentHandlers[]; +extern const char kDeleteAfterLoad[]; extern const char kDisableCache[]; +extern const char kEnableSandbox[]; extern const char kForceInProcess[]; extern const char kHelp[]; extern const char kMapOrigin[]; diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc index 345351e..9538f5a 100644 --- a/mojo/shell/application_manager.cc +++ b/mojo/shell/application_manager.cc @@ -382,15 +382,22 @@ void ApplicationManager::HandleFetchCallback( options = url_to_native_options_[base_resolved_url]; } - fetcher->AsPath( - blocking_pool_, - base::Bind(&ApplicationManager::RunNativeApplication, - weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()), - options, cleanup, base::Passed(fetcher.Pass()))); + // TODO(erg): Have a better way of switching the sandbox on. For now, switch + // it on hard coded when we're using some of the sandboxable core services. + bool start_sandboxed = false; + if (app_url == GURL("mojo://core_services/") && qualifier == "Sandboxed Core") + start_sandboxed = true; + + fetcher->AsPath(blocking_pool_, + base::Bind(&ApplicationManager::RunNativeApplication, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(request.Pass()), start_sandboxed, + options, cleanup, base::Passed(fetcher.Pass()))); } void ApplicationManager::RunNativeApplication( InterfaceRequest<Application> application_request, + bool start_sandboxed, const NativeRunnerFactory::Options& options, NativeApplicationCleanup cleanup, scoped_ptr<Fetcher> fetcher, @@ -411,7 +418,7 @@ void ApplicationManager::RunNativeApplication( path.AsUTF8Unsafe()); NativeRunner* runner = native_runner_factory_->Create(options).release(); native_runners_.push_back(runner); - runner->Start(path, cleanup, application_request.Pass(), + runner->Start(path, start_sandboxed, cleanup, application_request.Pass(), base::Bind(&ApplicationManager::CleanupRunner, weak_ptr_factory_.GetWeakPtr(), runner)); } diff --git a/mojo/shell/application_manager.h b/mojo/shell/application_manager.h index e744a8a..b1613f7 100644 --- a/mojo/shell/application_manager.h +++ b/mojo/shell/application_manager.h @@ -210,6 +210,7 @@ class ApplicationManager { scoped_ptr<Fetcher> fetcher); void RunNativeApplication(InterfaceRequest<Application> application_request, + bool start_sandboxed, const NativeRunnerFactory::Options& options, NativeApplicationCleanup cleanup, scoped_ptr<Fetcher> fetcher, diff --git a/mojo/shell/native_runner.h b/mojo/shell/native_runner.h index ad89f44..847908f 100644 --- a/mojo/shell/native_runner.h +++ b/mojo/shell/native_runner.h @@ -37,6 +37,7 @@ class NativeRunner { // factory's Create(). Rationale: The factory may need information from the // file to decide what kind of NativeRunner to make. virtual void Start(const base::FilePath& app_path, + bool start_sandboxed, NativeApplicationCleanup cleanup, InterfaceRequest<Application> application_request, const base::Closure& app_completed_callback) = 0; |