Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: remoting/host/win/unprivileged_process_delegate.cc

Issue 11118005: Pass the client end handle of the network-to-daemon IPC channel via handle inheritance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 // This file implements the Windows service controlling Me2Me host processes 5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions. 6 // running within user sessions.
7 7
8 #include "remoting/host/win/unprivileged_process_delegate.h" 8 #include "remoting/host/win/unprivileged_process_delegate.h"
9 9
10 #include "base/base_switches.h" 10 #include "base/base_switches.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
14 #include "base/stringprintf.h"
14 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
15 #include "base/win/scoped_handle.h" 16 #include "base/win/scoped_handle.h"
17 #include "ipc/ipc_channel_proxy.h"
18 #include "ipc/ipc_message.h"
16 #include "remoting/host/win/launch_process_with_token.h" 19 #include "remoting/host/win/launch_process_with_token.h"
17 20
18 using base::win::ScopedHandle; 21 using base::win::ScopedHandle;
19 22
20 namespace { 23 namespace {
21 24
22 // The command line switch specifying the name of the daemon IPC endpoint. 25 // Match the pipe name prefix used by Chrome IPC channels so that the client
23 const char kDaemonIpcSwitchName[] = "daemon-pipe"; 26 // could use Chrome IPC APIs instead of connecting manually.
simonmorris 2012/10/12 16:31:13 Both of these constants appear in more than one fi
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
27 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
28
29 // The command line switches specifying the daemon IPC endpoint.
simonmorris 2012/10/12 16:31:13 switches -> switch?
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
30 const char kDaemonPipeSwitchName[] = "daemon-pipe";
31
32 // The security descriptor of the daemon IPC endpoint. It gives full access
33 // to LocalSystem and denies access by anyone else.
34 const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)";
24 35
25 // The command line parameters that should be copied from the service's command 36 // The command line parameters that should be copied from the service's command
26 // line to the host process. 37 // line to the host process.
27 const char* kCopiedSwitchNames[] = { 38 const char* kCopiedSwitchNames[] = {
28 "host-config", switches::kV, switches::kVModule }; 39 "host-config", switches::kV, switches::kVModule };
29 40
30 } // namespace 41 } // namespace
31 42
32 namespace remoting { 43 namespace remoting {
33 44
34 UnprivilegedProcessDelegate::UnprivilegedProcessDelegate( 45 UnprivilegedProcessDelegate::UnprivilegedProcessDelegate(
35 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 46 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
36 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 47 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
37 const FilePath& binary_path) 48 const FilePath& binary_path)
38 : main_task_runner_(main_task_runner), 49 : main_task_runner_(main_task_runner),
39 io_task_runner_(io_task_runner), 50 io_task_runner_(io_task_runner),
40 binary_path_(binary_path) { 51 binary_path_(binary_path) {
41 } 52 }
42 53
43 UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() { 54 UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() {
44 KillProcess(CONTROL_C_EXIT); 55 KillProcess(CONTROL_C_EXIT);
45 } 56 }
46 57
58 bool UnprivilegedProcessDelegate::Send(IPC::Message* message) {
59 DCHECK(main_task_runner_->BelongsToCurrentThread());
60
61 return channel_->Send(message);
62 }
63
47 DWORD UnprivilegedProcessDelegate::GetExitCode() { 64 DWORD UnprivilegedProcessDelegate::GetExitCode() {
48 DCHECK(main_task_runner_->BelongsToCurrentThread()); 65 DCHECK(main_task_runner_->BelongsToCurrentThread());
49 66
50 DWORD exit_code = CONTROL_C_EXIT; 67 DWORD exit_code = CONTROL_C_EXIT;
51 if (worker_process_.IsValid()) { 68 if (worker_process_.IsValid()) {
52 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { 69 if (!::GetExitCodeProcess(worker_process_, &exit_code)) {
53 LOG_GETLASTERROR(INFO) 70 LOG_GETLASTERROR(INFO)
54 << "Failed to query the exit code of the worker process"; 71 << "Failed to query the exit code of the worker process";
55 exit_code = CONTROL_C_EXIT; 72 exit_code = CONTROL_C_EXIT;
56 } 73 }
57 } 74 }
58 75
59 return exit_code; 76 return exit_code;
60 } 77 }
61 78
62 void UnprivilegedProcessDelegate::KillProcess(DWORD exit_code) { 79 void UnprivilegedProcessDelegate::KillProcess(DWORD exit_code) {
63 DCHECK(main_task_runner_->BelongsToCurrentThread()); 80 DCHECK(main_task_runner_->BelongsToCurrentThread());
64 81
82 channel_.reset();
83
65 if (worker_process_.IsValid()) { 84 if (worker_process_.IsValid()) {
66 TerminateProcess(worker_process_, exit_code); 85 TerminateProcess(worker_process_, exit_code);
67 } 86 }
68 } 87 }
69 88
70 bool UnprivilegedProcessDelegate::LaunchProcess( 89 bool UnprivilegedProcessDelegate::LaunchProcess(
71 const std::string& channel_name, 90 IPC::Listener* delegate,
72 ScopedHandle* process_exit_event_out) { 91 ScopedHandle* process_exit_event_out) {
73 DCHECK(main_task_runner_->BelongsToCurrentThread()); 92 DCHECK(main_task_runner_->BelongsToCurrentThread());
93 // Generate a unique name of the channel.
simonmorris 2012/10/12 16:31:13 of -> for
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
94 std::string channel_name = GenerateIpcChannelName(this);
95
96 // Create a connected IPC channel.
97 ScopedHandle client;
98 scoped_ptr<IPC::ChannelProxy> server;
99 if (!CreateConnectedIpcChannel(channel_name, delegate, &client, &server))
100 return false;
101
102 // Convert the handle value into a decimal integer. Handle values are 32bit
103 // even on 64bit platforms.
104 std::string pipe_handle = base::StringPrintf(
105 "%d", reinterpret_cast<ULONG_PTR>(client.Get()));
74 106
75 // Create the command line passing the name of the IPC channel to use and 107 // Create the command line passing the name of the IPC channel to use and
76 // copying known switches from the caller's command line. 108 // copying known switches from the caller's command line.
77 CommandLine command_line(binary_path_); 109 CommandLine command_line(binary_path_);
78 command_line.AppendSwitchNative(kDaemonIpcSwitchName, 110 command_line.AppendSwitchASCII(kDaemonPipeSwitchName, pipe_handle);
79 UTF8ToWide(channel_name));
80 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 111 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
81 kCopiedSwitchNames, 112 kCopiedSwitchNames,
82 arraysize(kCopiedSwitchNames)); 113 arraysize(kCopiedSwitchNames));
83 114
84 // Try to launch the process. 115 // Try to launch the process.
85 // TODO(alexeypa): Pass a restricted process token. 116 // TODO(alexeypa): Pass a restricted process token.
86 // See http://crbug.com/134694. 117 // See http://crbug.com/134694.
87 ScopedHandle worker_thread; 118 ScopedHandle worker_thread;
88 worker_process_.Close(); 119 worker_process_.Close();
89 if (!LaunchProcessWithToken(command_line.GetProgram(), 120 if (!LaunchProcessWithToken(command_line.GetProgram(),
90 command_line.GetCommandLineString(), 121 command_line.GetCommandLineString(),
91 NULL, 122 NULL,
123 true,
92 0, 124 0,
93 &worker_process_, 125 &worker_process_,
94 &worker_thread)) { 126 &worker_thread)) {
95 return false; 127 return false;
96 } 128 }
97 129
98 // Return a handle that the caller can wait on to get notified when 130 // Return a handle that the caller can wait on to get notified when
99 // the process terminates. 131 // the process terminates.
100 ScopedHandle process_exit_event; 132 ScopedHandle process_exit_event;
101 if (!DuplicateHandle(GetCurrentProcess(), 133 if (!DuplicateHandle(GetCurrentProcess(),
102 worker_process_, 134 worker_process_,
103 GetCurrentProcess(), 135 GetCurrentProcess(),
104 process_exit_event.Receive(), 136 process_exit_event.Receive(),
105 SYNCHRONIZE, 137 SYNCHRONIZE,
106 FALSE, 138 FALSE,
107 0)) { 139 0)) {
108 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle"; 140 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle";
109 KillProcess(CONTROL_C_EXIT); 141 KillProcess(CONTROL_C_EXIT);
110 return false; 142 return false;
111 } 143 }
112 144
145 channel_ = server.Pass();
113 *process_exit_event_out = process_exit_event.Pass(); 146 *process_exit_event_out = process_exit_event.Pass();
114 return true; 147 return true;
115 } 148 }
116 149
150 bool UnprivilegedProcessDelegate::CreateConnectedIpcChannel(
151 std::string channel_name,
simonmorris 2012/10/12 16:31:13 std::string -> const std::string& ?
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
152 IPC::Listener* delegate,
153 ScopedHandle* client_out,
154 scoped_ptr<IPC::ChannelProxy>* server_out) {
155 // Create the server end of the channel.
156 scoped_ptr<IPC::ChannelProxy> server;
157 if (!CreateIpcChannel(channel_name, kDaemonIpcSecurityDescriptor,
158 io_task_runner_, delegate, &server)) {
159 return false;
160 }
161
162 // Convert the channel name to the pipe name.
163 std::string pipe_name(kChromePipeNamePrefix);
164 pipe_name.append(channel_name);
165
166 // Create the client end of the channel. This code should match the code in
167 // IPC::Channel.
168 ScopedHandle client;
169 SECURITY_ATTRIBUTES security_attributes = { sizeof(security_attributes), NULL,
170 TRUE };
simonmorris 2012/10/12 16:31:13 This seems an unnecessarily opaque way to initiali
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
171 client.Set(CreateFile(UTF8ToUTF16(pipe_name).c_str(),
172 GENERIC_READ | GENERIC_WRITE,
173 0,
174 &security_attributes,
175 OPEN_EXISTING,
176 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
177 FILE_FLAG_OVERLAPPED,
178 NULL));
179 if (!client.IsValid())
180 return false;
181
182 *client_out = client.Pass();
183 *server_out = server.Pass();
184 return true;
185 }
186
117 } // namespace remoting 187 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698