OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
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 "chrome/nacl/nacl_broker_listener.h" | |
6 | |
7 #include "base/base_switches.h" | |
8 #include "base/bind.h" | |
9 #include "base/command_line.h" | |
10 #include "base/message_loop.h" | |
11 #include "base/message_loop/message_loop_proxy.h" | |
12 #include "base/path_service.h" | |
13 #include "base/process_util.h" | |
14 #include "chrome/common/chrome_switches.h" | |
15 #include "chrome/common/nacl_cmd_line.h" | |
16 #include "chrome/common/nacl_debug_exception_handler_win.h" | |
17 #include "chrome/common/nacl_messages.h" | |
18 #include "content/public/common/sandbox_init.h" | |
19 #include "ipc/ipc_channel.h" | |
20 #include "ipc/ipc_switches.h" | |
21 #include "sandbox/win/src/sandbox_policy.h" | |
22 | |
23 namespace { | |
24 | |
25 void SendReply(IPC::Channel* channel, int32 pid, bool result) { | |
26 channel->Send(new NaClProcessMsg_DebugExceptionHandlerLaunched(pid, result)); | |
27 } | |
28 | |
29 } // namespace | |
30 | |
31 NaClBrokerListener::NaClBrokerListener() | |
32 : browser_handle_(base::kNullProcessHandle) { | |
33 } | |
34 | |
35 NaClBrokerListener::~NaClBrokerListener() { | |
36 base::CloseProcessHandle(browser_handle_); | |
37 } | |
38 | |
39 void NaClBrokerListener::Listen() { | |
40 std::string channel_name = | |
41 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
42 switches::kProcessChannelID); | |
43 channel_.reset(new IPC::Channel( | |
44 channel_name, IPC::Channel::MODE_CLIENT, this)); | |
45 CHECK(channel_->Connect()); | |
46 base::MessageLoop::current()->Run(); | |
47 } | |
48 | |
49 // NOTE: changes to this method need to be reviewed by the security team. | |
50 void NaClBrokerListener::PreSpawnTarget(sandbox::TargetPolicy* policy, | |
51 bool* success) { | |
52 // This code is duplicated in chrome_content_browser_client.cc. | |
53 | |
54 // Allow the server side of a pipe restricted to the "chrome.nacl." | |
55 // namespace so that it cannot impersonate other system or other chrome | |
56 // service pipes. | |
57 sandbox::ResultCode result = policy->AddRule( | |
58 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | |
59 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | |
60 L"\\\\.\\pipe\\chrome.nacl.*"); | |
61 *success = (result == sandbox::SBOX_ALL_OK); | |
62 } | |
63 | |
64 void NaClBrokerListener::OnChannelConnected(int32 peer_pid) { | |
65 bool res = base::OpenPrivilegedProcessHandle(peer_pid, &browser_handle_); | |
66 CHECK(res); | |
67 } | |
68 | |
69 bool NaClBrokerListener::OnMessageReceived(const IPC::Message& msg) { | |
70 bool handled = true; | |
71 IPC_BEGIN_MESSAGE_MAP(NaClBrokerListener, msg) | |
72 IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchLoaderThroughBroker, | |
73 OnLaunchLoaderThroughBroker) | |
74 IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchDebugExceptionHandler, | |
75 OnLaunchDebugExceptionHandler) | |
76 IPC_MESSAGE_HANDLER(NaClProcessMsg_StopBroker, OnStopBroker) | |
77 IPC_MESSAGE_UNHANDLED(handled = false) | |
78 IPC_END_MESSAGE_MAP() | |
79 return handled; | |
80 } | |
81 | |
82 void NaClBrokerListener::OnChannelError() { | |
83 // The browser died unexpectedly, quit to avoid a zombie process. | |
84 base::MessageLoop::current()->Quit(); | |
85 } | |
86 | |
87 void NaClBrokerListener::OnLaunchLoaderThroughBroker( | |
88 const std::string& loader_channel_id) { | |
89 base::ProcessHandle loader_process = 0; | |
90 base::ProcessHandle loader_handle_in_browser = 0; | |
91 | |
92 // Create the path to the nacl broker/loader executable - it's the executable | |
93 // this code is running in. | |
94 base::FilePath exe_path; | |
95 PathService::Get(base::FILE_EXE, &exe_path); | |
96 if (!exe_path.empty()) { | |
97 CommandLine* cmd_line = new CommandLine(exe_path); | |
98 nacl::CopyNaClCommandLineArguments(cmd_line); | |
99 | |
100 cmd_line->AppendSwitchASCII(switches::kProcessType, | |
101 switches::kNaClLoaderProcess); | |
102 | |
103 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, | |
104 loader_channel_id); | |
105 | |
106 loader_process = content::StartSandboxedProcess(this, cmd_line); | |
107 if (loader_process) { | |
108 DuplicateHandle(::GetCurrentProcess(), loader_process, | |
109 browser_handle_, &loader_handle_in_browser, | |
110 PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION , FALSE, 0); | |
111 base::CloseProcessHandle(loader_process); | |
112 } | |
113 } | |
114 channel_->Send(new NaClProcessMsg_LoaderLaunched(loader_channel_id, | |
115 loader_handle_in_browser)); | |
116 } | |
117 | |
118 void NaClBrokerListener::OnLaunchDebugExceptionHandler( | |
119 int32 pid, base::ProcessHandle process_handle, | |
120 const std::string& startup_info) { | |
121 NaClStartDebugExceptionHandlerThread( | |
122 process_handle, startup_info, | |
123 base::MessageLoopProxy::current(), | |
124 base::Bind(SendReply, channel_.get(), pid)); | |
125 } | |
126 | |
127 void NaClBrokerListener::OnStopBroker() { | |
128 base::MessageLoop::current()->Quit(); | |
129 } | |
OLD | NEW |