1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/nacl/browser/nacl_broker_host_win.h"
6
7 #include <windows.h>
8
9 #include <memory>
10
11 #include "base/base_switches.h"
12 #include "base/command_line.h"
13 #include "base/memory/ptr_util.h"
14 #include "components/nacl/browser/nacl_broker_service_win.h"
15 #include "components/nacl/browser/nacl_browser.h"
16 #include "components/nacl/common/nacl_cmd_line.h"
17 #include "components/nacl/common/nacl_constants.h"
18 #include "components/nacl/common/nacl_messages.h"
19 #include "components/nacl/common/nacl_process_type.h"
20 #include "components/nacl/common/nacl_switches.h"
21 #include "content/public/browser/browser_child_process_host.h"
22 #include "content/public/browser/child_process_data.h"
23 #include "content/public/browser/child_process_host.h"
24 #include "content/public/common/content_switches.h"
25 #include "content/public/common/sandboxed_process_launcher_delegate.h"
26 #include "sandbox/policy/mojom/sandbox.mojom.h"
27
28 namespace {
29 // NOTE: changes to this class need to be reviewed by the security team.
30 class NaClBrokerSandboxedProcessLauncherDelegate
31 : public content::SandboxedProcessLauncherDelegate {
32 public:
NaClBrokerSandboxedProcessLauncherDelegate()33 NaClBrokerSandboxedProcessLauncherDelegate() {}
34
35 NaClBrokerSandboxedProcessLauncherDelegate(
36 const NaClBrokerSandboxedProcessLauncherDelegate&) = delete;
37 NaClBrokerSandboxedProcessLauncherDelegate& operator=(
38 const NaClBrokerSandboxedProcessLauncherDelegate&) = delete;
39
GetSandboxType()40 sandbox::mojom::Sandbox GetSandboxType() override {
41 return sandbox::mojom::Sandbox::kNoSandbox;
42 }
43
GetSandboxTag()44 std::string GetSandboxTag() override {
45 // kNoSandbox does not use a TargetPolicy, if the sandbox type is changed
46 // then provide a unique tag here.
47 return "";
48 }
49 };
50 } // namespace
51
52 namespace nacl {
53
NaClBrokerHost()54 NaClBrokerHost::NaClBrokerHost() : is_terminating_(false) {
55 }
56
~NaClBrokerHost()57 NaClBrokerHost::~NaClBrokerHost() {
58 }
59
Init()60 bool NaClBrokerHost::Init() {
61 DCHECK(!process_);
62 process_ = content::BrowserChildProcessHost::Create(
63 static_cast<content::ProcessType>(PROCESS_TYPE_NACL_BROKER), this,
64 content::ChildProcessHost::IpcMode::kLegacy);
65 process_->SetMetricsName("NaCl Broker");
66 process_->GetHost()->CreateChannelMojo();
67
68 // Create the path to the nacl broker/loader executable.
69 base::FilePath nacl_path;
70 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&nacl_path))
71 return false;
72
73 base::CommandLine* cmd_line = new base::CommandLine(nacl_path);
74 CopyNaClCommandLineArguments(cmd_line);
75
76 cmd_line->AppendSwitchASCII(switches::kProcessType,
77 switches::kNaClBrokerProcess);
78 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed())
79 cmd_line->AppendSwitch(switches::kNoErrorDialogs);
80
81 process_->Launch(
82 std::make_unique<NaClBrokerSandboxedProcessLauncherDelegate>(),
83 base::WrapUnique(cmd_line), true);
84 return true;
85 }
86
OnMessageReceived(const IPC::Message & msg)87 bool NaClBrokerHost::OnMessageReceived(const IPC::Message& msg) {
88 bool handled = true;
89 IPC_BEGIN_MESSAGE_MAP(NaClBrokerHost, msg)
90 IPC_MESSAGE_HANDLER(NaClProcessMsg_LoaderLaunched, OnLoaderLaunched)
91 IPC_MESSAGE_HANDLER(NaClProcessMsg_DebugExceptionHandlerLaunched,
92 OnDebugExceptionHandlerLaunched)
93 IPC_MESSAGE_UNHANDLED(handled = false)
94 IPC_END_MESSAGE_MAP()
95 return handled;
96 }
97
LaunchLoader(int launch_id,mojo::ScopedMessagePipeHandle ipc_channel_handle)98 bool NaClBrokerHost::LaunchLoader(
99 int launch_id,
100 mojo::ScopedMessagePipeHandle ipc_channel_handle) {
101 return process_->Send(new NaClProcessMsg_LaunchLoaderThroughBroker(
102 launch_id, ipc_channel_handle.release()));
103 }
104
OnLoaderLaunched(int launch_id,base::ProcessHandle handle)105 void NaClBrokerHost::OnLoaderLaunched(int launch_id,
106 base::ProcessHandle handle) {
107 NaClBrokerService::GetInstance()->OnLoaderLaunched(launch_id,
108 base::Process(handle));
109 }
110
LaunchDebugExceptionHandler(int32_t pid,base::ProcessHandle process_handle,const std::string & startup_info)111 bool NaClBrokerHost::LaunchDebugExceptionHandler(
112 int32_t pid,
113 base::ProcessHandle process_handle,
114 const std::string& startup_info) {
115 base::ProcessHandle broker_process =
116 process_->GetData().GetProcess().Handle();
117 base::ProcessHandle handle_in_broker_process;
118 if (!DuplicateHandle(::GetCurrentProcess(), process_handle,
119 broker_process, &handle_in_broker_process,
120 0, /* bInheritHandle= */ FALSE, DUPLICATE_SAME_ACCESS))
121 return false;
122 return process_->Send(new NaClProcessMsg_LaunchDebugExceptionHandler(
123 pid, handle_in_broker_process, startup_info));
124 }
125
OnDebugExceptionHandlerLaunched(int32_t pid,bool success)126 void NaClBrokerHost::OnDebugExceptionHandlerLaunched(int32_t pid,
127 bool success) {
128 NaClBrokerService::GetInstance()->OnDebugExceptionHandlerLaunched(pid,
129 success);
130 }
131
StopBroker()132 void NaClBrokerHost::StopBroker() {
133 is_terminating_ = true;
134 process_->Send(new NaClProcessMsg_StopBroker());
135 }
136
137 } // namespace nacl
138