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

Side by Side Diff: remoting/host/win/wts_session_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/wts_session_process_delegate.h" 8 #include "remoting/host/win/wts_session_process_delegate.h"
9 9
10 #include <sddl.h>
11 #include <limits>
12
13 #include "base/base_switches.h" 10 #include "base/base_switches.h"
14 #include "base/bind.h" 11 #include "base/bind.h"
15 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
16 #include "base/command_line.h" 13 #include "base/command_line.h"
17 #include "base/file_path.h" 14 #include "base/file_path.h"
18 #include "base/file_util.h" 15 #include "base/file_util.h"
19 #include "base/logging.h" 16 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop.h" 18 #include "base/message_loop.h"
22 #include "base/path_service.h" 19 #include "base/path_service.h"
23 #include "base/single_thread_task_runner.h" 20 #include "base/single_thread_task_runner.h"
24 #include "base/time.h"
25 #include "base/timer.h"
26 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
27 #include "base/win/scoped_handle.h" 22 #include "base/win/scoped_handle.h"
28 #include "base/win/windows_version.h" 23 #include "base/win/windows_version.h"
29 #include "ipc/ipc_channel.h" 24 #include "ipc/ipc_channel.h"
30 #include "ipc/ipc_channel_proxy.h" 25 #include "ipc/ipc_channel_proxy.h"
31 #include "ipc/ipc_message.h" 26 #include "ipc/ipc_message.h"
32 #include "remoting/host/host_exit_codes.h" 27 #include "remoting/host/host_exit_codes.h"
33 #include "remoting/host/win/launch_process_with_token.h" 28 #include "remoting/host/win/launch_process_with_token.h"
34 #include "remoting/host/win/worker_process_launcher.h" 29 #include "remoting/host/win/worker_process_launcher.h"
35 #include "remoting/host/win/wts_console_monitor.h" 30 #include "remoting/host/win/wts_console_monitor.h"
36 #include "remoting/host/worker_process_ipc_delegate.h" 31 #include "remoting/host/worker_process_ipc_delegate.h"
37 32
38 using base::TimeDelta;
39 using base::win::ScopedHandle; 33 using base::win::ScopedHandle;
40 34
41 const FilePath::CharType kDaemonBinaryName[] = 35 const FilePath::CharType kDaemonBinaryName[] =
42 FILE_PATH_LITERAL("remoting_daemon.exe"); 36 FILE_PATH_LITERAL("remoting_daemon.exe");
43 37
44 // The command line switch specifying the name of the daemon IPC endpoint. 38 // The command line switch specifying the name of the daemon IPC endpoint.
45 const char kDaemonIpcSwitchName[] = "daemon-pipe"; 39 const char kDaemonPipeSwitchName[] = "daemon-pipe";
46 40
47 const char kElevateSwitchName[] = "elevate"; 41 const char kElevateSwitchName[] = "elevate";
48 42
49 // The command line parameters that should be copied from the service's command 43 // The command line parameters that should be copied from the service's command
50 // line to the host process. 44 // line to the host process.
51 const char* kCopiedSwitchNames[] = { 45 const char* kCopiedSwitchNames[] = {
52 "host-config", switches::kV, switches::kVModule }; 46 "host-config", switches::kV, switches::kVModule };
53 47
54 namespace remoting { 48 namespace remoting {
55 49
56 // A private class actually implementing the functionality provided by 50 // A private class actually implementing the functionality provided by
57 // |WtsSessionProcessDelegate|. This class is ref-counted and implements 51 // |WtsSessionProcessDelegate|. This class is ref-counted and implements
58 // asynchronous fire-and-forget shutdown. 52 // asynchronous fire-and-forget shutdown.
59 class WtsSessionProcessDelegate::Core 53 class WtsSessionProcessDelegate::Core
60 : public base::RefCountedThreadSafe<WtsSessionProcessDelegate::Core>, 54 : public base::RefCountedThreadSafe<WtsSessionProcessDelegate::Core>,
61 public base::MessagePumpForIO::IOHandler, 55 public base::MessagePumpForIO::IOHandler,
62 public WorkerProcessLauncher::Delegate { 56 public WorkerProcessLauncher::Delegate {
63 public: 57 public:
64 // The caller must ensure that |delegate| remains valid at least until 58 // The caller must ensure that |delegate| remains valid at least until
65 // Stop() method has been called. 59 // Stop() method has been called.
66 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 60 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
67 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 61 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
68 const FilePath& binary_path, 62 const FilePath& binary_path,
69 bool launch_elevated); 63 bool launch_elevated,
64 const std::string& channel_security);
70 65
71 // base::MessagePumpForIO::IOHandler implementation. 66 // base::MessagePumpForIO::IOHandler implementation.
72 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context, 67 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context,
73 DWORD bytes_transferred, 68 DWORD bytes_transferred,
74 DWORD error) OVERRIDE; 69 DWORD error) OVERRIDE;
75 70
71 // IPC::Sender implementation.
72 virtual bool Send(IPC::Message* message) OVERRIDE;
73
76 // WorkerProcessLauncher::Delegate implementation. 74 // WorkerProcessLauncher::Delegate implementation.
77 virtual DWORD GetExitCode() OVERRIDE; 75 virtual DWORD GetExitCode() OVERRIDE;
78 virtual void KillProcess(DWORD exit_code) OVERRIDE; 76 virtual void KillProcess(DWORD exit_code) OVERRIDE;
79 virtual bool LaunchProcess( 77 virtual bool LaunchProcess(
80 const std::string& channel_name, 78 IPC::Listener* delegate,
81 base::win::ScopedHandle* process_exit_event_out) OVERRIDE; 79 base::win::ScopedHandle* process_exit_event_out) OVERRIDE;
82 80
83 // Initializes the object returning true on success. 81 // Initializes the object returning true on success.
84 bool Initialize(uint32 session_id); 82 bool Initialize(uint32 session_id);
85 83
86 // Stops the object asynchronously. 84 // Stops the object asynchronously.
87 void Stop(); 85 void Stop();
88 86
89 private: 87 private:
90 friend class base::RefCountedThreadSafe<Core>; 88 friend class base::RefCountedThreadSafe<Core>;
(...skipping 18 matching lines...) Expand all
109 107
110 // The task runner all public methods of this class should be called on. 108 // The task runner all public methods of this class should be called on.
111 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 109 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
112 110
113 // The task runner serving job object notifications. 111 // The task runner serving job object notifications.
114 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 112 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
115 113
116 // Path to the worker process binary. 114 // Path to the worker process binary.
117 FilePath binary_path_; 115 FilePath binary_path_;
118 116
117 // The server end of the IPC channel used to commonicate to the worker
simonmorris 2012/10/12 16:31:13 commonicate -> communicate
alexeypa (please no reviews) 2012/10/12 18:44:39 Done.
118 // process.
119 scoped_ptr<IPC::ChannelProxy> channel_;
120
121 // Security descriptor (as SDDL) to be applied to |channel_|.
122 std::string channel_security_;
123
119 // The job object used to control the lifetime of child processes. 124 // The job object used to control the lifetime of child processes.
120 base::win::ScopedHandle job_; 125 base::win::ScopedHandle job_;
121 126
122 // True if the worker process should be launched elevated. 127 // True if the worker process should be launched elevated.
123 bool launch_elevated_; 128 bool launch_elevated_;
124 129
125 // A handle that becomes signalled once all processes associated with the job 130 // A handle that becomes signalled once all processes associated with the job
126 // have been terminated. 131 // have been terminated.
127 base::win::ScopedHandle process_exit_event_; 132 base::win::ScopedHandle process_exit_event_;
128 133
129 // The token to be used to launch a process in a different session. 134 // The token to be used to launch a process in a different session.
130 base::win::ScopedHandle session_token_; 135 base::win::ScopedHandle session_token_;
131 136
132 // True if Stop() has been called. 137 // True if Stop() has been called.
133 bool stopping_; 138 bool stopping_;
134 139
135 // The handle of the worker process, if launched. 140 // The handle of the worker process, if launched.
136 base::win::ScopedHandle worker_process_; 141 base::win::ScopedHandle worker_process_;
137 142
138 DISALLOW_COPY_AND_ASSIGN(Core); 143 DISALLOW_COPY_AND_ASSIGN(Core);
139 }; 144 };
140 145
141 WtsSessionProcessDelegate::Core::Core( 146 WtsSessionProcessDelegate::Core::Core(
142 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 147 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
143 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 148 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
144 const FilePath& binary_path, 149 const FilePath& binary_path,
145 bool launch_elevated) 150 bool launch_elevated,
151 const std::string& channel_security)
146 : main_task_runner_(main_task_runner), 152 : main_task_runner_(main_task_runner),
147 io_task_runner_(io_task_runner), 153 io_task_runner_(io_task_runner),
148 binary_path_(binary_path), 154 binary_path_(binary_path),
155 channel_security_(channel_security),
149 launch_elevated_(launch_elevated), 156 launch_elevated_(launch_elevated),
150 stopping_(false) { 157 stopping_(false) {
151 DCHECK(main_task_runner_->BelongsToCurrentThread()); 158 DCHECK(main_task_runner_->BelongsToCurrentThread());
152 } 159 }
153 160
154 void WtsSessionProcessDelegate::Core::OnIOCompleted( 161 void WtsSessionProcessDelegate::Core::OnIOCompleted(
155 base::MessagePumpForIO::IOContext* context, 162 base::MessagePumpForIO::IOContext* context,
156 DWORD bytes_transferred, 163 DWORD bytes_transferred,
157 DWORD error) { 164 DWORD error) {
158 DCHECK(io_task_runner_->BelongsToCurrentThread()); 165 DCHECK(io_task_runner_->BelongsToCurrentThread());
159 166
160 // |bytes_transferred| is used in job object notifications to supply 167 // |bytes_transferred| is used in job object notifications to supply
161 // the message ID; |context| carries process ID. 168 // the message ID; |context| carries process ID.
162 main_task_runner_->PostTask(FROM_HERE, base::Bind( 169 main_task_runner_->PostTask(FROM_HERE, base::Bind(
163 &Core::OnJobNotification, this, bytes_transferred, 170 &Core::OnJobNotification, this, bytes_transferred,
164 reinterpret_cast<DWORD>(context))); 171 reinterpret_cast<DWORD>(context)));
165 } 172 }
166 173
174 bool WtsSessionProcessDelegate::Core::Send(IPC::Message* message) {
175 DCHECK(main_task_runner_->BelongsToCurrentThread());
176
177 if (channel_.get()) {
178 return channel_->Send(message);
179 } else {
180 delete message;
181 return false;
182 }
183 }
184
167 DWORD WtsSessionProcessDelegate::Core::GetExitCode() { 185 DWORD WtsSessionProcessDelegate::Core::GetExitCode() {
168 DCHECK(main_task_runner_->BelongsToCurrentThread()); 186 DCHECK(main_task_runner_->BelongsToCurrentThread());
169 187
170 DWORD exit_code = CONTROL_C_EXIT; 188 DWORD exit_code = CONTROL_C_EXIT;
171 if (worker_process_.IsValid()) { 189 if (worker_process_.IsValid()) {
172 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { 190 if (!::GetExitCodeProcess(worker_process_, &exit_code)) {
173 LOG_GETLASTERROR(INFO) 191 LOG_GETLASTERROR(INFO)
174 << "Failed to query the exit code of the worker process"; 192 << "Failed to query the exit code of the worker process";
175 exit_code = CONTROL_C_EXIT; 193 exit_code = CONTROL_C_EXIT;
176 } 194 }
177 } 195 }
178 196
179 return exit_code; 197 return exit_code;
180 } 198 }
181 199
182 void WtsSessionProcessDelegate::Core::KillProcess(DWORD exit_code) { 200 void WtsSessionProcessDelegate::Core::KillProcess(DWORD exit_code) {
183 DCHECK(main_task_runner_->BelongsToCurrentThread()); 201 DCHECK(main_task_runner_->BelongsToCurrentThread());
184 202
203 channel_.reset();
204
185 if (launch_elevated_) { 205 if (launch_elevated_) {
186 if (job_.IsValid()) { 206 if (job_.IsValid()) {
187 TerminateJobObject(job_, exit_code); 207 TerminateJobObject(job_, exit_code);
188 } 208 }
189 } else { 209 } else {
190 if (worker_process_.IsValid()) { 210 if (worker_process_.IsValid()) {
191 TerminateProcess(worker_process_, exit_code); 211 TerminateProcess(worker_process_, exit_code);
192 } 212 }
193 } 213 }
194 } 214 }
195 215
196 bool WtsSessionProcessDelegate::Core::LaunchProcess( 216 bool WtsSessionProcessDelegate::Core::LaunchProcess(
197 const std::string& channel_name, 217 IPC::Listener* delegate,
198 ScopedHandle* process_exit_event_out) { 218 ScopedHandle* process_exit_event_out) {
199 DCHECK(main_task_runner_->BelongsToCurrentThread()); 219 DCHECK(main_task_runner_->BelongsToCurrentThread());
200 220
201 CommandLine command_line(CommandLine::NO_PROGRAM); 221 CommandLine command_line(CommandLine::NO_PROGRAM);
202 if (launch_elevated_) { 222 if (launch_elevated_) {
203 // The job object is not ready. Retry starting the host process later. 223 // The job object is not ready. Retry starting the host process later.
204 if (!job_.IsValid()) { 224 if (!job_.IsValid()) {
205 return false; 225 return false;
206 } 226 }
207 227
208 // Construct the helper binary name. 228 // Construct the helper binary name.
209 FilePath dir_path; 229 FilePath dir_path;
210 if (!PathService::Get(base::DIR_EXE, &dir_path)) { 230 if (!PathService::Get(base::DIR_EXE, &dir_path)) {
211 LOG(ERROR) << "Failed to get the executable file name."; 231 LOG(ERROR) << "Failed to get the executable file name.";
212 return false; 232 return false;
213 } 233 }
214 FilePath daemon_binary = dir_path.Append(kDaemonBinaryName); 234 FilePath daemon_binary = dir_path.Append(kDaemonBinaryName);
215 235
216 // Create the command line passing the name of the IPC channel to use and 236 // Create the command line passing the name of the IPC channel to use and
217 // copying known switches from the caller's command line. 237 // copying known switches from the caller's command line.
218 command_line.SetProgram(daemon_binary); 238 command_line.SetProgram(daemon_binary);
219 command_line.AppendSwitchPath(kElevateSwitchName, binary_path_); 239 command_line.AppendSwitchPath(kElevateSwitchName, binary_path_);
220 240
221 CHECK(ResetEvent(process_exit_event_)); 241 CHECK(ResetEvent(process_exit_event_));
222 } else { 242 } else {
223 command_line.SetProgram(binary_path_); 243 command_line.SetProgram(binary_path_);
224 } 244 }
225 245
246 // Create the server end of the IPC channel.
247 scoped_ptr<IPC::ChannelProxy> channel;
248 std::string channel_name = GenerateIpcChannelName(this);
249 if (!CreateIpcChannel(channel_name, channel_security_, io_task_runner_,
250 delegate, &channel))
251 return false;
252
226 // Create the command line passing the name of the IPC channel to use and 253 // Create the command line passing the name of the IPC channel to use and
227 // copying known switches from the caller's command line. 254 // copying known switches from the caller's command line.
228 command_line.AppendSwitchNative(kDaemonIpcSwitchName, 255 command_line.AppendSwitchNative(kDaemonPipeSwitchName,
229 UTF8ToWide(channel_name)); 256 UTF8ToWide(channel_name));
230 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 257 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
231 kCopiedSwitchNames, 258 kCopiedSwitchNames,
232 arraysize(kCopiedSwitchNames)); 259 arraysize(kCopiedSwitchNames));
233 260
234 // Try to launch the process. 261 // Try to launch the process.
235 ScopedHandle worker_process; 262 ScopedHandle worker_process;
236 ScopedHandle worker_thread; 263 ScopedHandle worker_thread;
237 if (!LaunchProcessWithToken(command_line.GetProgram(), 264 if (!LaunchProcessWithToken(command_line.GetProgram(),
238 command_line.GetCommandLineString(), 265 command_line.GetCommandLineString(),
239 session_token_, 266 session_token_,
267 false,
240 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, 268 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
241 &worker_process, 269 &worker_process,
242 &worker_thread)) { 270 &worker_thread)) {
243 return false; 271 return false;
244 } 272 }
245 273
246 HANDLE local_process_exit_event; 274 HANDLE local_process_exit_event;
247 if (launch_elevated_) { 275 if (launch_elevated_) {
248 if (!AssignProcessToJobObject(job_, worker_process)) { 276 if (!AssignProcessToJobObject(job_, worker_process)) {
249 LOG_GETLASTERROR(ERROR) 277 LOG_GETLASTERROR(ERROR)
(...skipping 22 matching lines...) Expand all
272 GetCurrentProcess(), 300 GetCurrentProcess(),
273 process_exit_event.Receive(), 301 process_exit_event.Receive(),
274 SYNCHRONIZE, 302 SYNCHRONIZE,
275 FALSE, 303 FALSE,
276 0)) { 304 0)) {
277 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle"; 305 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle";
278 KillProcess(CONTROL_C_EXIT); 306 KillProcess(CONTROL_C_EXIT);
279 return false; 307 return false;
280 } 308 }
281 309
310 channel_ = channel.Pass();
282 *process_exit_event_out = process_exit_event.Pass(); 311 *process_exit_event_out = process_exit_event.Pass();
283 return true; 312 return true;
284 } 313 }
285 314
286 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) { 315 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) {
287 if (base::win::GetVersion() == base::win::VERSION_XP) 316 if (base::win::GetVersion() == base::win::VERSION_XP)
288 launch_elevated_ = false; 317 launch_elevated_ = false;
289 318
290 if (launch_elevated_) { 319 if (launch_elevated_) {
291 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); 320 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 worker_process_.Set(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)); 441 worker_process_.Set(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid));
413 break; 442 break;
414 } 443 }
415 } 444 }
416 445
417 WtsSessionProcessDelegate::WtsSessionProcessDelegate( 446 WtsSessionProcessDelegate::WtsSessionProcessDelegate(
418 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 447 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
419 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 448 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
420 const FilePath& binary_path, 449 const FilePath& binary_path,
421 uint32 session_id, 450 uint32 session_id,
422 bool launch_elevated) { 451 bool launch_elevated,
452 const std::string& channel_security) {
423 core_ = new Core(main_task_runner, io_task_runner, binary_path, 453 core_ = new Core(main_task_runner, io_task_runner, binary_path,
424 launch_elevated); 454 launch_elevated, channel_security);
425 if (!core_->Initialize(session_id)) { 455 if (!core_->Initialize(session_id)) {
426 core_->Stop(); 456 core_->Stop();
427 core_ = NULL; 457 core_ = NULL;
428 } 458 }
429 } 459 }
430 460
431 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() { 461 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() {
432 core_->Stop(); 462 core_->Stop();
433 } 463 }
434 464
465 bool WtsSessionProcessDelegate::Send(IPC::Message* message) {
466 return core_->Send(message);
467 }
468
435 DWORD WtsSessionProcessDelegate::GetExitCode() { 469 DWORD WtsSessionProcessDelegate::GetExitCode() {
436 if (!core_) 470 if (!core_)
437 return CONTROL_C_EXIT; 471 return CONTROL_C_EXIT;
438 472
439 return core_->GetExitCode(); 473 return core_->GetExitCode();
440 } 474 }
441 475
442 void WtsSessionProcessDelegate::KillProcess(DWORD exit_code) { 476 void WtsSessionProcessDelegate::KillProcess(DWORD exit_code) {
443 if (core_) { 477 if (core_) {
444 core_->KillProcess(exit_code); 478 core_->KillProcess(exit_code);
445 } 479 }
446 } 480 }
447 481
448 bool WtsSessionProcessDelegate::LaunchProcess( 482 bool WtsSessionProcessDelegate::LaunchProcess(
449 const std::string& channel_name, 483 IPC::Listener* delegate,
450 base::win::ScopedHandle* process_exit_event_out) { 484 base::win::ScopedHandle* process_exit_event_out) {
451 if (!core_) 485 if (!core_)
452 return false; 486 return false;
453 487
454 return core_->LaunchProcess(channel_name, process_exit_event_out); 488 return core_->LaunchProcess(delegate, process_exit_event_out);
455 } 489 }
456 490
457 } // namespace remoting 491 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698