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

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

Issue 2446053002: Use ChannelMojo between the remoting daemon and desktop processes. (Closed)
Patch Set: rebase Created 4 years, 1 month 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
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 <utility> 10 #include <utility>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
18 #include "base/process/process_handle.h"
18 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
19 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
20 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/win/scoped_handle.h" 22 #include "base/win/scoped_handle.h"
22 #include "ipc/attachment_broker.h" 23 #include "ipc/attachment_broker.h"
23 #include "ipc/ipc_channel.h" 24 #include "ipc/ipc_channel.h"
24 #include "ipc/ipc_channel_proxy.h" 25 #include "ipc/ipc_channel_proxy.h"
25 #include "ipc/ipc_listener.h" 26 #include "ipc/ipc_listener.h"
26 #include "ipc/ipc_message.h" 27 #include "ipc/ipc_message.h"
28 #include "mojo/edk/embedder/embedder.h"
29 #include "mojo/edk/embedder/named_platform_channel_pair.h"
30 #include "mojo/edk/embedder/platform_channel_pair.h"
31 #include "mojo/edk/embedder/platform_handle_utils.h"
32 #include "mojo/edk/embedder/scoped_platform_handle.h"
27 #include "remoting/host/host_main.h" 33 #include "remoting/host/host_main.h"
28 #include "remoting/host/ipc_constants.h" 34 #include "remoting/host/ipc_constants.h"
29 #include "remoting/host/ipc_util.h"
30 #include "remoting/host/switches.h" 35 #include "remoting/host/switches.h"
31 #include "remoting/host/win/launch_process_with_token.h" 36 #include "remoting/host/win/launch_process_with_token.h"
32 #include "remoting/host/win/security_descriptor.h" 37 #include "remoting/host/win/security_descriptor.h"
33 #include "remoting/host/win/worker_process_launcher.h" 38 #include "remoting/host/win/worker_process_launcher.h"
34 #include "remoting/host/win/wts_terminal_monitor.h" 39 #include "remoting/host/win/wts_terminal_monitor.h"
35 #include "remoting/host/worker_process_ipc_delegate.h" 40 #include "remoting/host/worker_process_ipc_delegate.h"
36 41
37 using base::win::ScopedHandle; 42 using base::win::ScopedHandle;
38 43
39 // Name of the default session desktop. 44 // Name of the default session desktop.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // Creates and initializes the job object that will sandbox the launched child 99 // Creates and initializes the job object that will sandbox the launched child
95 // processes. 100 // processes.
96 void InitializeJob(ScopedHandle job); 101 void InitializeJob(ScopedHandle job);
97 102
98 // Notified that the job object initialization is complete. 103 // Notified that the job object initialization is complete.
99 void InitializeJobCompleted(ScopedHandle job); 104 void InitializeJobCompleted(ScopedHandle job);
100 105
101 // Called when the number of processes running in the job reaches zero. 106 // Called when the number of processes running in the job reaches zero.
102 void OnActiveProcessZero(); 107 void OnActiveProcessZero();
103 108
109 // Called when a process is launched in |job_|.
110 void OnProcessLaunchDetected(base::ProcessId pid);
111
104 void ReportFatalError(); 112 void ReportFatalError();
105 void ReportProcessLaunched(base::win::ScopedHandle worker_process); 113 void ReportProcessLaunched(base::win::ScopedHandle worker_process,
114 mojo::edk::ScopedPlatformHandle server_handle);
106 115
107 // The task runner all public methods of this class should be called on. 116 // The task runner all public methods of this class should be called on.
108 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 117 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
109 118
110 // The task runner serving job object notifications. 119 // The task runner serving job object notifications.
111 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 120 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
112 121
113 // The server end of the IPC channel used to communicate to the worker 122 // The server end of the IPC channel used to communicate to the worker
114 // process. 123 // process.
115 std::unique_ptr<IPC::ChannelProxy> channel_; 124 std::unique_ptr<IPC::ChannelProxy> channel_;
116 125
117 // Security descriptor (as SDDL) to be applied to |channel_|. 126 // Security descriptor (as SDDL) to be applied to |channel_|.
118 std::string channel_security_; 127 std::string channel_security_;
119 128
120 // Security descriptor (as SDDL) to be applied to the newly created process. 129 // Security descriptor (as SDDL) to be applied to the newly created process.
121 std::string new_process_security_; 130 std::string new_process_security_;
122 131
123 WorkerProcessLauncher* event_handler_; 132 WorkerProcessLauncher* event_handler_;
124 133
125 // Pointer to GetNamedPipeClientProcessId() API if it is available.
126 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*);
127 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_;
128
129 // The job object used to control the lifetime of child processes. 134 // The job object used to control the lifetime of child processes.
130 base::win::ScopedHandle job_; 135 base::win::ScopedHandle job_;
131 136
132 // True if the worker process should be launched elevated. 137 // True if the worker process should be launched elevated.
133 bool launch_elevated_; 138 bool launch_elevated_;
134 139
135 // True if a laucnh attemp is pending. 140 // True if a laucnh attemp is pending.
136 bool launch_pending_; 141 bool launch_pending_;
137 142
138 // The named pipe used as the transport by |channel_|.
139 base::win::ScopedHandle pipe_;
140
141 // The token to be used to launch a process in a different session. 143 // The token to be used to launch a process in a different session.
142 base::win::ScopedHandle session_token_; 144 base::win::ScopedHandle session_token_;
143 145
144 // Command line of the launched process. 146 // Command line of the launched process.
145 std::unique_ptr<base::CommandLine> target_command_; 147 std::unique_ptr<base::CommandLine> target_command_;
146 148
147 // The handle of the worker process, if launched. 149 // The handle of the worker process, if launched.
148 base::win::ScopedHandle worker_process_; 150 base::win::ScopedHandle worker_process_;
149 151
152 // If launching elevated, this holds the server handle after launch, until
153 // the final process launches.
154 mojo::edk::ScopedPlatformHandle elevated_server_handle_;
155
156 // If launching elevated, this is the pid of the launcher process.
157 base::ProcessId elevated_launcher_pid_ = base::kNullProcessId;
158
159 // The mojo child token for the process being launched.
160 std::string mojo_child_token_;
161
150 DISALLOW_COPY_AND_ASSIGN(Core); 162 DISALLOW_COPY_AND_ASSIGN(Core);
151 }; 163 };
152 164
153 WtsSessionProcessDelegate::Core::Core( 165 WtsSessionProcessDelegate::Core::Core(
154 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 166 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
155 std::unique_ptr<base::CommandLine> target_command, 167 std::unique_ptr<base::CommandLine> target_command,
156 bool launch_elevated, 168 bool launch_elevated,
157 const std::string& channel_security, 169 const std::string& channel_security,
158 const std::string& new_process_security) 170 const std::string& new_process_security)
159 : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), 171 : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
160 io_task_runner_(io_task_runner), 172 io_task_runner_(io_task_runner),
161 channel_security_(channel_security), 173 channel_security_(channel_security),
162 new_process_security_(new_process_security), 174 new_process_security_(new_process_security),
163 event_handler_(nullptr), 175 event_handler_(nullptr),
164 get_named_pipe_client_pid_(nullptr),
165 launch_elevated_(launch_elevated), 176 launch_elevated_(launch_elevated),
166 launch_pending_(false), 177 launch_pending_(false),
167 target_command_(std::move(target_command)) {} 178 target_command_(std::move(target_command)) {}
168 179
169 bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) { 180 bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) {
170 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 181 DCHECK(caller_task_runner_->BelongsToCurrentThread());
171 182
172 if (launch_elevated_) { 183 if (launch_elevated_) {
173 // GetNamedPipeClientProcessId() is available starting from Vista. 184 // GetNamedPipeClientProcessId() is available starting from Vista.
174 HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll"); 185 HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll");
175 CHECK(kernel32 != nullptr); 186 CHECK(kernel32 != nullptr);
176 187
177 get_named_pipe_client_pid_ =
178 reinterpret_cast<GetNamedPipeClientProcessIdFn>(
179 GetProcAddress(kernel32, "GetNamedPipeClientProcessId"));
180 CHECK(get_named_pipe_client_pid_ != nullptr);
181
182 ScopedHandle job; 188 ScopedHandle job;
183 job.Set(CreateJobObject(nullptr, nullptr)); 189 job.Set(CreateJobObject(nullptr, nullptr));
184 if (!job.IsValid()) { 190 if (!job.IsValid()) {
185 PLOG(ERROR) << "Failed to create a job object"; 191 PLOG(ERROR) << "Failed to create a job object";
186 return false; 192 return false;
187 } 193 }
188 194
189 // Limit the number of active processes in the job to two (the helper 195 // Limit the number of active processes in the job to two (the helper
190 // process performing elevation and the worker process itself) and make sure 196 // process performing elevation and the worker process itself) and make sure
191 // that all processes will be killed once the job object is destroyed. 197 // that all processes will be killed once the job object is destroyed.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 252
247 void WtsSessionProcessDelegate::Core::CloseChannel() { 253 void WtsSessionProcessDelegate::Core::CloseChannel() {
248 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 254 DCHECK(caller_task_runner_->BelongsToCurrentThread());
249 255
250 if (!channel_) 256 if (!channel_)
251 return; 257 return;
252 258
253 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel( 259 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
254 channel_.get()); 260 channel_.get());
255 channel_.reset(); 261 channel_.reset();
256 pipe_.Close(); 262 elevated_server_handle_.reset();
263 elevated_launcher_pid_ = base::kNullProcessId;
264 if (!mojo_child_token_.empty()) {
265 mojo::edk::ChildProcessLaunchFailed(mojo_child_token_);
266 mojo_child_token_.clear();
267 }
257 } 268 }
258 269
259 void WtsSessionProcessDelegate::Core::KillProcess() { 270 void WtsSessionProcessDelegate::Core::KillProcess() {
260 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 271 DCHECK(caller_task_runner_->BelongsToCurrentThread());
261 272
262 CloseChannel(); 273 CloseChannel();
263 274
264 event_handler_ = nullptr; 275 event_handler_ = nullptr;
265 launch_pending_ = false; 276 launch_pending_ = false;
266 277
267 if (launch_elevated_) { 278 if (launch_elevated_) {
268 if (job_.IsValid()) 279 if (job_.IsValid())
269 TerminateJobObject(job_.Get(), CONTROL_C_EXIT); 280 TerminateJobObject(job_.Get(), CONTROL_C_EXIT);
270 } else { 281 } else {
271 if (worker_process_.IsValid()) 282 if (worker_process_.IsValid())
272 TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT); 283 TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT);
273 } 284 }
274 285
275 worker_process_.Close(); 286 worker_process_.Close();
276 } 287 }
277 288
278 WtsSessionProcessDelegate::Core::~Core() { 289 WtsSessionProcessDelegate::Core::~Core() {
279 DCHECK(!channel_); 290 DCHECK(!channel_);
280 DCHECK(!event_handler_); 291 DCHECK(!event_handler_);
281 DCHECK(!pipe_.IsValid());
282 DCHECK(!worker_process_.IsValid()); 292 DCHECK(!worker_process_.IsValid());
283 } 293 }
284 294
285 void WtsSessionProcessDelegate::Core::OnIOCompleted( 295 void WtsSessionProcessDelegate::Core::OnIOCompleted(
286 base::MessagePumpForIO::IOContext* context, 296 base::MessagePumpForIO::IOContext* context,
287 DWORD bytes_transferred, 297 DWORD bytes_transferred,
288 DWORD error) { 298 DWORD error) {
289 DCHECK(io_task_runner_->BelongsToCurrentThread()); 299 DCHECK(io_task_runner_->BelongsToCurrentThread());
290 300
291 // |bytes_transferred| is used in job object notifications to supply 301 // |bytes_transferred| is used in job object notifications to supply
292 // the message ID; |context| carries process ID. 302 // the message ID; |context| carries process ID.
293 if (bytes_transferred == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) { 303 switch (bytes_transferred) {
294 caller_task_runner_->PostTask(FROM_HERE, 304 case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: {
295 base::Bind(&Core::OnActiveProcessZero, this)); 305 caller_task_runner_->PostTask(
306 FROM_HERE, base::Bind(&Core::OnActiveProcessZero, this));
307 break;
308 }
309 case JOB_OBJECT_MSG_NEW_PROCESS: {
310 caller_task_runner_->PostTask(
311 FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
312 reinterpret_cast<base::ProcessId>(context)));
313 break;
314 }
296 } 315 }
297 } 316 }
298 317
299 bool WtsSessionProcessDelegate::Core::OnMessageReceived( 318 bool WtsSessionProcessDelegate::Core::OnMessageReceived(
300 const IPC::Message& message) { 319 const IPC::Message& message) {
301 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 320 DCHECK(caller_task_runner_->BelongsToCurrentThread());
302 321
303 return event_handler_->OnMessageReceived(message); 322 return event_handler_->OnMessageReceived(message);
304 } 323 }
305 324
306 void WtsSessionProcessDelegate::Core::OnChannelConnected(int32_t peer_pid) { 325 void WtsSessionProcessDelegate::Core::OnChannelConnected(int32_t peer_pid) {
307 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 326 DCHECK(caller_task_runner_->BelongsToCurrentThread());
308 327
309 // Report the worker PID now if the worker process is launched indirectly.
310 // Note that in this case the pipe's security descriptor is the only
311 // protection against a malicious processed connecting to the pipe.
312 if (launch_elevated_) {
313 DWORD pid;
314 if (!get_named_pipe_client_pid_(pipe_.Get(), &pid)) {
315 PLOG(ERROR) << "Failed to retrive PID of the client";
316 ReportFatalError();
317 return;
318 }
319
320 if (pid != static_cast<DWORD>(peer_pid)) {
321 LOG(ERROR) << "The actual client PID " << pid
322 << " does not match the one reported by the client: "
323 << peer_pid;
324 ReportFatalError();
325 return;
326 }
327
328 DWORD desired_access =
329 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
330 ScopedHandle worker_process(OpenProcess(desired_access, false, pid));
331 if (!worker_process.IsValid()) {
332 PLOG(ERROR) << "Failed to open process " << pid;
333 ReportFatalError();
334 return;
335 }
336
337 ReportProcessLaunched(std::move(worker_process));
338 }
339
340 if (event_handler_) 328 if (event_handler_)
341 event_handler_->OnChannelConnected(peer_pid); 329 event_handler_->OnChannelConnected(peer_pid);
342 } 330 }
343 331
344 void WtsSessionProcessDelegate::Core::OnChannelError() { 332 void WtsSessionProcessDelegate::Core::OnChannelError() {
345 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 333 DCHECK(caller_task_runner_->BelongsToCurrentThread());
346 334
347 event_handler_->OnChannelError(); 335 event_handler_->OnChannelError();
348 } 336 }
349 337
350 void WtsSessionProcessDelegate::Core::DoLaunchProcess() { 338 void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
351 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 339 DCHECK(caller_task_runner_->BelongsToCurrentThread());
352 DCHECK(!channel_); 340 DCHECK(!channel_);
353 DCHECK(!pipe_.IsValid());
354 DCHECK(!worker_process_.IsValid()); 341 DCHECK(!worker_process_.IsValid());
355 342
356 base::CommandLine command_line(target_command_->argv()); 343 base::CommandLine command_line(target_command_->argv());
357 if (launch_elevated_) { 344 if (launch_elevated_) {
358 // The job object is not ready. Retry starting the host process later. 345 // The job object is not ready. Retry starting the host process later.
359 if (!job_.IsValid()) { 346 if (!job_.IsValid()) {
360 launch_pending_ = true; 347 launch_pending_ = true;
361 return; 348 return;
362 } 349 }
363 350
364 // Construct the helper binary name. 351 // Construct the helper binary name.
365 base::FilePath helper_binary; 352 base::FilePath helper_binary;
366 if (!GetInstalledBinaryPath(kHostBinaryName, &helper_binary)) { 353 if (!GetInstalledBinaryPath(kHostBinaryName, &helper_binary)) {
367 ReportFatalError(); 354 ReportFatalError();
368 return; 355 return;
369 } 356 }
370 357
371 // Create the command line passing the name of the IPC channel to use and 358 // Create the command line passing the name of the IPC channel to use and
372 // copying known switches from the caller's command line. 359 // copying known switches from the caller's command line.
373 command_line.SetProgram(helper_binary); 360 command_line.SetProgram(helper_binary);
374 command_line.AppendSwitchPath(kElevateSwitchName, 361 command_line.AppendSwitchPath(kElevateSwitchName,
375 target_command_->GetProgram()); 362 target_command_->GetProgram());
376 } 363 }
377 364
378 // Create the server end of the IPC channel. 365 const std::string mojo_message_pipe_token = mojo::edk::GenerateRandomToken();
379 std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID(); 366 mojo_child_token_ = mojo::edk::GenerateRandomToken();
380 ScopedHandle pipe;
381 if (!CreateIpcChannel(channel_name, channel_security_, &pipe)) {
382 ReportFatalError();
383 return;
384 }
385
386 // Wrap the pipe into an IPC channel.
387 std::unique_ptr<IPC::ChannelProxy> channel( 367 std::unique_ptr<IPC::ChannelProxy> channel(
388 new IPC::ChannelProxy(this, io_task_runner_)); 368 new IPC::ChannelProxy(this, io_task_runner_));
389 IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel( 369 IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
390 channel.get(), io_task_runner_); 370 channel.get(), io_task_runner_);
391 channel->Init(IPC::ChannelHandle(pipe.Get()), IPC::Channel::MODE_SERVER, 371 channel->Init(mojo::edk::CreateParentMessagePipe(mojo_message_pipe_token,
392 /*create_pipe_now=*/true); 372 mojo_child_token_)
373 .release(),
374 IPC::Channel::MODE_SERVER, /*create_pipe_now=*/true);
375 command_line.AppendSwitchASCII(kMojoPipeToken, mojo_message_pipe_token);
393 376
394 // Pass the name of the IPC channel to use. 377 std::unique_ptr<mojo::edk::PlatformChannelPair> normal_mojo_channel;
395 command_line.AppendSwitchNative(kDaemonPipeSwitchName, 378 std::unique_ptr<mojo::edk::NamedPlatformChannelPair> elevated_mojo_channel;
396 base::UTF8ToWide(channel_name)); 379 base::HandlesToInheritVector handles_to_inherit;
380 if (launch_elevated_) {
381 // Pass the name of the IPC channel to use.
382 mojo::edk::NamedPlatformChannelPair::Options options;
383 options.security_descriptor = base::UTF8ToUTF16(channel_security_);
384 elevated_mojo_channel =
385 base::MakeUnique<mojo::edk::NamedPlatformChannelPair>(options);
386 elevated_mojo_channel->PrepareToPassClientHandleToChildProcess(
387 &command_line);
388 } else {
389 normal_mojo_channel = base::MakeUnique<mojo::edk::PlatformChannelPair>();
390 normal_mojo_channel->PrepareToPassClientHandleToChildProcess(
391 &command_line, &handles_to_inherit);
392 }
397 393
398 ScopedSd security_descriptor; 394 ScopedSd security_descriptor;
399 std::unique_ptr<SECURITY_ATTRIBUTES> security_attributes; 395 std::unique_ptr<SECURITY_ATTRIBUTES> security_attributes;
400 if (!new_process_security_.empty()) { 396 if (!new_process_security_.empty()) {
401 security_descriptor = ConvertSddlToSd(new_process_security_); 397 security_descriptor = ConvertSddlToSd(new_process_security_);
402 if (!security_descriptor) { 398 if (!security_descriptor) {
403 PLOG(ERROR) << "ConvertSddlToSd() failed."; 399 PLOG(ERROR) << "ConvertSddlToSd() failed.";
404 ReportFatalError(); 400 ReportFatalError();
405 return; 401 return;
406 } 402 }
407 403
408 security_attributes.reset(new SECURITY_ATTRIBUTES()); 404 security_attributes.reset(new SECURITY_ATTRIBUTES());
409 security_attributes->nLength = sizeof(SECURITY_ATTRIBUTES); 405 security_attributes->nLength = sizeof(SECURITY_ATTRIBUTES);
410 security_attributes->lpSecurityDescriptor = security_descriptor.get(); 406 security_attributes->lpSecurityDescriptor = security_descriptor.get();
411 security_attributes->bInheritHandle = FALSE; 407 security_attributes->bInheritHandle = FALSE;
412 } 408 }
413 409
414 // Try to launch the process. 410 // Try to launch the process.
415 ScopedHandle worker_process; 411 ScopedHandle worker_process;
416 ScopedHandle worker_thread; 412 ScopedHandle worker_thread;
417 if (!LaunchProcessWithToken( 413 if (!LaunchProcessWithToken(
418 command_line.GetProgram(), command_line.GetCommandLineString(), 414 command_line.GetProgram(), command_line.GetCommandLineString(),
419 session_token_.Get(), security_attributes.get(), 415 session_token_.Get(), security_attributes.get(),
420 /* thread_attributes= */ nullptr, /* handles_to_inherit=*/{}, 416 /* thread_attributes= */ nullptr, handles_to_inherit,
421 /* creation_flags= */ CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, 417 /* creation_flags= */ CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
422 base::UTF8ToUTF16(kDefaultDesktopName).c_str(), &worker_process, 418 base::UTF8ToUTF16(kDefaultDesktopName).c_str(), &worker_process,
423 &worker_thread)) { 419 &worker_thread)) {
424 ReportFatalError(); 420 ReportFatalError();
425 return; 421 return;
426 } 422 }
427 423
428 if (launch_elevated_) { 424 if (launch_elevated_) {
429 if (!AssignProcessToJobObject(job_.Get(), worker_process.Get())) { 425 if (!AssignProcessToJobObject(job_.Get(), worker_process.Get())) {
430 PLOG(ERROR) << "Failed to assign the worker to the job object"; 426 PLOG(ERROR) << "Failed to assign the worker to the job object";
431 ReportFatalError(); 427 ReportFatalError();
432 return; 428 return;
433 } 429 }
434 } 430 }
435 431
436 if (!ResumeThread(worker_thread.Get())) { 432 if (!ResumeThread(worker_thread.Get())) {
437 PLOG(ERROR) << "Failed to resume the worker thread"; 433 PLOG(ERROR) << "Failed to resume the worker thread";
438 ReportFatalError(); 434 ReportFatalError();
439 return; 435 return;
440 } 436 }
441 437
442 channel_ = std::move(channel); 438 channel_ = std::move(channel);
443 pipe_ = std::move(pipe);
444 439
445 // Report success if the worker process is lauched directly. Otherwise, PID of 440 if (launch_elevated_) {
446 // the client connected to the pipe will be used later. See 441 // When launching an elevated worker process, an intermediate launcher
447 // OnChannelConnected(). 442 // process launches the worker process. Reporting the launch waits until the
448 if (!launch_elevated_) 443 // worker process launch is detected. Until then, store the values needed in
449 ReportProcessLaunched(std::move(worker_process)); 444 // fields. See OnProcessLaunchDetected for their use.
445 elevated_server_handle_ = elevated_mojo_channel->PassServerHandle();
446 elevated_launcher_pid_ = GetProcessId(worker_process.Get());
447 DCHECK(elevated_server_handle_.is_valid());
448 } else {
449 ReportProcessLaunched(std::move(worker_process),
450 normal_mojo_channel->PassServerHandle());
451 }
450 } 452 }
451 453
452 void WtsSessionProcessDelegate::Core::DrainJobNotifications() { 454 void WtsSessionProcessDelegate::Core::DrainJobNotifications() {
453 DCHECK(io_task_runner_->BelongsToCurrentThread()); 455 DCHECK(io_task_runner_->BelongsToCurrentThread());
454 456
455 // DrainJobNotifications() is posted after the job object is destroyed, so 457 // DrainJobNotifications() is posted after the job object is destroyed, so
456 // by this time all notifications from the job object have been processed 458 // by this time all notifications from the job object have been processed
457 // already. Let the main thread know that the queue has been drained. 459 // already. Let the main thread know that the queue has been drained.
458 caller_task_runner_->PostTask(FROM_HERE, base::Bind( 460 caller_task_runner_->PostTask(FROM_HERE, base::Bind(
459 &Core::DrainJobNotificationsCompleted, this)); 461 &Core::DrainJobNotificationsCompleted, this));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() { 501 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() {
500 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 502 DCHECK(caller_task_runner_->BelongsToCurrentThread());
501 503
502 if (launch_pending_) { 504 if (launch_pending_) {
503 LOG(ERROR) << "The worker process exited before connecting via IPC."; 505 LOG(ERROR) << "The worker process exited before connecting via IPC.";
504 launch_pending_ = false; 506 launch_pending_ = false;
505 ReportFatalError(); 507 ReportFatalError();
506 } 508 }
507 } 509 }
508 510
511 void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected(
512 base::ProcessId pid) {
joedow 2016/10/26 21:48:20 Thanks for moving this out of the OnClientConnecte
Sam McNally 2016/10/27 00:43:46 Indeed, the connection will not be usable by anoth
513 DCHECK(caller_task_runner_->BelongsToCurrentThread());
514 if (!elevated_server_handle_.is_valid())
515 return;
516
517 if (pid == elevated_launcher_pid_)
518 return;
519
520 DWORD desired_access =
521 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
522 base::win::ScopedHandle worker_process(
523 OpenProcess(desired_access, false, pid));
524 if (!worker_process.IsValid()) {
525 PLOG(ERROR) << "Failed to open process " << pid;
526 ReportFatalError();
527 return;
528 }
529 elevated_launcher_pid_ = base::kNullProcessId;
530 ReportProcessLaunched(std::move(worker_process),
531 std::move(elevated_server_handle_));
532 }
533
509 void WtsSessionProcessDelegate::Core::ReportFatalError() { 534 void WtsSessionProcessDelegate::Core::ReportFatalError() {
510 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 535 DCHECK(caller_task_runner_->BelongsToCurrentThread());
511 536
512 CloseChannel(); 537 CloseChannel();
513 538
514 WorkerProcessLauncher* event_handler = event_handler_; 539 WorkerProcessLauncher* event_handler = event_handler_;
515 event_handler_ = nullptr; 540 event_handler_ = nullptr;
516 event_handler->OnFatalError(); 541 event_handler->OnFatalError();
517 } 542 }
518 543
519 void WtsSessionProcessDelegate::Core::ReportProcessLaunched( 544 void WtsSessionProcessDelegate::Core::ReportProcessLaunched(
520 base::win::ScopedHandle worker_process) { 545 base::win::ScopedHandle worker_process,
546 mojo::edk::ScopedPlatformHandle server_handle) {
521 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 547 DCHECK(caller_task_runner_->BelongsToCurrentThread());
522 DCHECK(!worker_process_.IsValid()); 548 DCHECK(!worker_process_.IsValid());
523 549
550 mojo::edk::ChildProcessLaunched(worker_process.Get(),
551 std::move(server_handle),
552 mojo_child_token_);
553 mojo_child_token_.clear();
524 worker_process_ = std::move(worker_process); 554 worker_process_ = std::move(worker_process);
525 555
526 // Report a handle that can be used to wait for the worker process completion, 556 // Report a handle that can be used to wait for the worker process completion,
527 // query information about the process and duplicate handles. 557 // query information about the process and duplicate handles.
528 DWORD desired_access = 558 DWORD desired_access =
529 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; 559 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
530 HANDLE temp_handle; 560 HANDLE temp_handle;
531 if (!DuplicateHandle(GetCurrentProcess(), worker_process_.Get(), 561 if (!DuplicateHandle(GetCurrentProcess(), worker_process_.Get(),
532 GetCurrentProcess(), &temp_handle, desired_access, FALSE, 562 GetCurrentProcess(), &temp_handle, desired_access, FALSE,
533 0)) { 563 0)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 599
570 void WtsSessionProcessDelegate::CloseChannel() { 600 void WtsSessionProcessDelegate::CloseChannel() {
571 core_->CloseChannel(); 601 core_->CloseChannel();
572 } 602 }
573 603
574 void WtsSessionProcessDelegate::KillProcess() { 604 void WtsSessionProcessDelegate::KillProcess() {
575 core_->KillProcess(); 605 core_->KillProcess();
576 } 606 }
577 607
578 } // namespace remoting 608 } // namespace remoting
OLDNEW
« remoting/host/desktop_process_main.cc ('K') | « remoting/host/switches.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698