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 // This file implements the Windows service controlling Me2Me host processes 6 // running within user sessions. 7 8 #include "remoting/host/win/wts_session_process_delegate.h" 9 10 #include "base/bind.h" 11 #include "base/command_line.h" 12 #include "base/files/file_path.h" 13 #include "base/logging.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/single_thread_task_runner.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/thread_task_runner_handle.h" 18 #include "base/win/scoped_handle.h" 19 #include "base/win/windows_version.h" 20 #include "ipc/ipc_channel.h" 21 #include "ipc/ipc_channel_proxy.h" 22 #include "ipc/ipc_listener.h" 23 #include "ipc/ipc_message.h" 24 #include "remoting/host/host_main.h" 25 #include "remoting/host/ipc_constants.h" 26 #include "remoting/host/ipc_util.h" 27 #include "remoting/host/win/launch_process_with_token.h" 28 #include "remoting/host/win/worker_process_launcher.h" 29 #include "remoting/host/win/wts_terminal_monitor.h" 30 #include "remoting/host/worker_process_ipc_delegate.h" 31 32 using base::win::ScopedHandle; 33 34 // Name of the default session desktop. 35 const char kDefaultDesktopName[] = "winsta0\\default"; 36 37 namespace remoting { 38 39 // A private class actually implementing the functionality provided by 40 // |WtsSessionProcessDelegate|. This class is ref-counted and implements 41 // asynchronous fire-and-forget shutdown. 42 class WtsSessionProcessDelegate::Core 43 : public base::RefCountedThreadSafe<Core>, 44 public base::MessagePumpForIO::IOHandler, 45 public IPC::Listener { 46 public: 47 Core(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 48 scoped_ptr<CommandLine> target, 49 bool launch_elevated, 50 const std::string& channel_security); 51 52 // Initializes the object returning true on success. 53 bool Initialize(uint32 session_id); 54 55 // Stops the object asynchronously. 56 void Stop(); 57 58 // Mirrors WorkerProcessLauncher::Delegate. 59 void LaunchProcess(WorkerProcessLauncher* event_handler); 60 void Send(IPC::Message* message); 61 void CloseChannel(); 62 void KillProcess(); 63 64 private: 65 friend class base::RefCountedThreadSafe<Core>; 66 virtual ~Core(); 67 68 // base::MessagePumpForIO::IOHandler implementation. 69 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context, 70 DWORD bytes_transferred, 71 DWORD error) OVERRIDE; 72 73 // IPC::Listener implementation. 74 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 75 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 76 virtual void OnChannelError() OVERRIDE; 77 78 // The actual implementation of LaunchProcess() 79 void DoLaunchProcess(); 80 81 // Drains the completion port queue to make sure that all job object 82 // notifications have been received. 83 void DrainJobNotifications(); 84 85 // Notified that the completion port queue has been drained. 86 void DrainJobNotificationsCompleted(); 87 88 // Creates and initializes the job object that will sandbox the launched child 89 // processes. 90 void InitializeJob(scoped_ptr<base::win::ScopedHandle> job); 91 92 // Notified that the job object initialization is complete. 93 void InitializeJobCompleted(scoped_ptr<base::win::ScopedHandle> job); 94 95 // Called when the number of processes running in the job reaches zero. 96 void OnActiveProcessZero(); 97 98 void ReportFatalError(); 99 void ReportProcessLaunched(base::win::ScopedHandle worker_process); 100 101 // The task runner all public methods of this class should be called on. 102 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 103 104 // The task runner serving job object notifications. 105 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 106 107 // The server end of the IPC channel used to communicate to the worker 108 // process. 109 scoped_ptr<IPC::ChannelProxy> channel_; 110 111 // Security descriptor (as SDDL) to be applied to |channel_|. 112 std::string channel_security_; 113 114 WorkerProcessLauncher* event_handler_; 115 116 // Pointer to GetNamedPipeClientProcessId() API if it is available. 117 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); 118 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; 119 120 // The job object used to control the lifetime of child processes. 121 base::win::ScopedHandle job_; 122 123 // True if the worker process should be launched elevated. 124 bool launch_elevated_; 125 126 // True if a laucnh attemp is pending. 127 bool launch_pending_; 128 129 // The named pipe used as the transport by |channel_|. 130 base::win::ScopedHandle pipe_; 131 132 // The token to be used to launch a process in a different session. 133 base::win::ScopedHandle session_token_; 134 135 // Command line of the launched process. 136 scoped_ptr<CommandLine> target_command_; 137 138 // The handle of the worker process, if launched. 139 base::win::ScopedHandle worker_process_; 140 141 DISALLOW_COPY_AND_ASSIGN(Core); 142 }; 143 144 WtsSessionProcessDelegate::Core::Core( 145 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 146 scoped_ptr<CommandLine> target_command, 147 bool launch_elevated, 148 const std::string& channel_security) 149 : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), 150 io_task_runner_(io_task_runner), 151 channel_security_(channel_security), 152 event_handler_(NULL), 153 get_named_pipe_client_pid_(NULL), 154 launch_elevated_(launch_elevated), 155 launch_pending_(false), 156 target_command_(target_command.Pass()) { 157 } 158 159 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) { 160 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 161 162 // Windows XP does not support elevation. 163 if (base::win::GetVersion() < base::win::VERSION_VISTA) 164 launch_elevated_ = false; 165 166 if (launch_elevated_) { 167 // GetNamedPipeClientProcessId() is available starting from Vista. 168 HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll"); 169 CHECK(kernel32 != NULL); 170 171 get_named_pipe_client_pid_ = 172 reinterpret_cast<GetNamedPipeClientProcessIdFn>( 173 GetProcAddress(kernel32, "GetNamedPipeClientProcessId")); 174 CHECK(get_named_pipe_client_pid_ != NULL); 175 176 ScopedHandle job; 177 job.Set(CreateJobObject(NULL, NULL)); 178 if (!job.IsValid()) { 179 LOG_GETLASTERROR(ERROR) << "Failed to create a job object"; 180 return false; 181 } 182 183 // Limit the number of active processes in the job to two (the helper 184 // process performing elevation and the worker process itself) and make sure 185 // that all processes will be killed once the job object is destroyed. 186 JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; 187 memset(&info, 0, sizeof(info)); 188 info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS | 189 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; 190 info.BasicLimitInformation.ActiveProcessLimit = 2; 191 if (!SetInformationJobObject(job, 192 JobObjectExtendedLimitInformation, 193 &info, 194 sizeof(info))) { 195 LOG_GETLASTERROR(ERROR) << "Failed to set limits on the job object"; 196 return false; 197 } 198 199 // ScopedHandle is not compatible with base::Passed, so we wrap it to 200 // a scoped pointer. 201 scoped_ptr<ScopedHandle> job_wrapper(new ScopedHandle()); 202 *job_wrapper = job.Pass(); 203 204 // To receive job object notifications the job object is registered with 205 // the completion port represented by |io_task_runner|. The registration has 206 // to be done on the I/O thread because 207 // MessageLoopForIO::RegisterJobObject() can only be called via 208 // MessageLoopForIO::current(). 209 io_task_runner_->PostTask( 210 FROM_HERE, 211 base::Bind(&Core::InitializeJob, this, base::Passed(&job_wrapper))); 212 } 213 214 // Create a session token for the launched process. 215 return CreateSessionToken(session_id, &session_token_); 216 } 217 218 void WtsSessionProcessDelegate::Core::Stop() { 219 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 220 221 KillProcess(); 222 223 // Drain the completion queue to make sure all job object notifications have 224 // been received. 225 DrainJobNotificationsCompleted(); 226 } 227 228 void WtsSessionProcessDelegate::Core::LaunchProcess( 229 WorkerProcessLauncher* event_handler) { 230 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 231 DCHECK(!event_handler_); 232 233 event_handler_ = event_handler; 234 DoLaunchProcess(); 235 } 236 237 void WtsSessionProcessDelegate::Core::Send(IPC::Message* message) { 238 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 239 240 if (channel_) { 241 channel_->Send(message); 242 } else { 243 delete message; 244 } 245 } 246 247 void WtsSessionProcessDelegate::Core::CloseChannel() { 248 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 249 250 channel_.reset(); 251 pipe_.Close(); 252 } 253 254 void WtsSessionProcessDelegate::Core::KillProcess() { 255 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 256 257 channel_.reset(); 258 event_handler_ = NULL; 259 launch_pending_ = false; 260 pipe_.Close(); 261 262 if (launch_elevated_) { 263 if (job_.IsValid()) 264 TerminateJobObject(job_, CONTROL_C_EXIT); 265 } else { 266 if (worker_process_.IsValid()) 267 TerminateProcess(worker_process_, CONTROL_C_EXIT); 268 } 269 270 worker_process_.Close(); 271 } 272 273 WtsSessionProcessDelegate::Core::~Core() { 274 DCHECK(!channel_); 275 DCHECK(!event_handler_); 276 DCHECK(!pipe_.IsValid()); 277 DCHECK(!worker_process_.IsValid()); 278 } 279 280 void WtsSessionProcessDelegate::Core::OnIOCompleted( 281 base::MessagePumpForIO::IOContext* context, 282 DWORD bytes_transferred, 283 DWORD error) { 284 DCHECK(io_task_runner_->BelongsToCurrentThread()); 285 286 // |bytes_transferred| is used in job object notifications to supply 287 // the message ID; |context| carries process ID. 288 if (bytes_transferred == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) { 289 caller_task_runner_->PostTask(FROM_HERE, 290 base::Bind(&Core::OnActiveProcessZero, this)); 291 } 292 } 293 294 bool WtsSessionProcessDelegate::Core::OnMessageReceived( 295 const IPC::Message& message) { 296 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 297 298 return event_handler_->OnMessageReceived(message); 299 } 300 301 void WtsSessionProcessDelegate::Core::OnChannelConnected(int32 peer_pid) { 302 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 303 304 // Report the worker PID now if the worker process is launched indirectly. 305 // Note that in this case the pipe's security descriptor is the only 306 // protection against a malicious processed connecting to the pipe. 307 if (launch_elevated_) { 308 DWORD pid; 309 if (!get_named_pipe_client_pid_(pipe_, &pid)) { 310 LOG_GETLASTERROR(ERROR) << "Failed to retrive PID of the client"; 311 ReportFatalError(); 312 return; 313 } 314 315 if (pid != static_cast<DWORD>(peer_pid)) { 316 LOG(ERROR) << "The actual client PID " << pid 317 << " does not match the one reported by the client: " 318 << peer_pid; 319 ReportFatalError(); 320 return; 321 } 322 323 DWORD desired_access = 324 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; 325 ScopedHandle worker_process(OpenProcess(desired_access, false, pid)); 326 if (!worker_process.IsValid()) { 327 LOG_GETLASTERROR(ERROR) << "Failed to open process " << pid; 328 ReportFatalError(); 329 return; 330 } 331 332 ReportProcessLaunched(worker_process.Pass()); 333 } 334 335 if (event_handler_) 336 event_handler_->OnChannelConnected(peer_pid); 337 } 338 339 void WtsSessionProcessDelegate::Core::OnChannelError() { 340 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 341 342 event_handler_->OnChannelError(); 343 } 344 345 void WtsSessionProcessDelegate::Core::DoLaunchProcess() { 346 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 347 DCHECK(!channel_); 348 DCHECK(!pipe_.IsValid()); 349 DCHECK(!worker_process_.IsValid()); 350 351 CommandLine command_line(target_command_->argv()); 352 if (launch_elevated_) { 353 // The job object is not ready. Retry starting the host process later. 354 if (!job_.IsValid()) { 355 launch_pending_ = true; 356 return; 357 } 358 359 // Construct the helper binary name. 360 base::FilePath helper_binary; 361 if (!GetInstalledBinaryPath(kHostBinaryName, &helper_binary)) { 362 ReportFatalError(); 363 return; 364 } 365 366 // Create the command line passing the name of the IPC channel to use and 367 // copying known switches from the caller's command line. 368 command_line.SetProgram(helper_binary); 369 command_line.AppendSwitchPath(kElevateSwitchName, 370 target_command_->GetProgram()); 371 } 372 373 // Create the server end of the IPC channel. 374 std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID(); 375 ScopedHandle pipe; 376 if (!CreateIpcChannel(channel_name, channel_security_, &pipe)) { 377 ReportFatalError(); 378 return; 379 } 380 381 // Wrap the pipe into an IPC channel. 382 scoped_ptr<IPC::ChannelProxy> channel(new IPC::ChannelProxy( 383 IPC::ChannelHandle(pipe), 384 IPC::Channel::MODE_SERVER, 385 this, 386 io_task_runner_)); 387 388 // Pass the name of the IPC channel to use. 389 command_line.AppendSwitchNative(kDaemonPipeSwitchName, 390 UTF8ToWide(channel_name)); 391 392 // Try to launch the process. 393 ScopedHandle worker_process; 394 ScopedHandle worker_thread; 395 if (!LaunchProcessWithToken(command_line.GetProgram(), 396 command_line.GetCommandLineString(), 397 session_token_, 398 NULL, 399 NULL, 400 false, 401 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, 402 UTF8ToUTF16(kDefaultDesktopName).c_str(), 403 &worker_process, 404 &worker_thread)) { 405 ReportFatalError(); 406 return; 407 } 408 409 if (launch_elevated_) { 410 if (!AssignProcessToJobObject(job_, worker_process)) { 411 LOG_GETLASTERROR(ERROR) 412 << "Failed to assign the worker to the job object"; 413 ReportFatalError(); 414 return; 415 } 416 } 417 418 if (!ResumeThread(worker_thread)) { 419 LOG_GETLASTERROR(ERROR) << "Failed to resume the worker thread"; 420 ReportFatalError(); 421 return; 422 } 423 424 channel_ = channel.Pass(); 425 pipe_ = pipe.Pass(); 426 427 // Report success if the worker process is lauched directly. Otherwise, PID of 428 // the client connected to the pipe will be used later. See 429 // OnChannelConnected(). 430 if (!launch_elevated_) 431 ReportProcessLaunched(worker_process.Pass()); 432 } 433 434 void WtsSessionProcessDelegate::Core::DrainJobNotifications() { 435 DCHECK(io_task_runner_->BelongsToCurrentThread()); 436 437 // DrainJobNotifications() is posted after the job object is destroyed, so 438 // by this time all notifications from the job object have been processed 439 // already. Let the main thread know that the queue has been drained. 440 caller_task_runner_->PostTask(FROM_HERE, base::Bind( 441 &Core::DrainJobNotificationsCompleted, this)); 442 } 443 444 void WtsSessionProcessDelegate::Core::DrainJobNotificationsCompleted() { 445 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 446 447 if (job_.IsValid()) { 448 job_.Close(); 449 450 // Drain the completion queue to make sure all job object notification have 451 // been received. 452 io_task_runner_->PostTask(FROM_HERE, base::Bind( 453 &Core::DrainJobNotifications, this)); 454 } 455 } 456 457 void WtsSessionProcessDelegate::Core::InitializeJob( 458 scoped_ptr<base::win::ScopedHandle> job) { 459 DCHECK(io_task_runner_->BelongsToCurrentThread()); 460 461 // Register to receive job notifications via the I/O thread's completion port. 462 if (!base::MessageLoopForIO::current()->RegisterJobObject(job->Get(), this)) { 463 LOG_GETLASTERROR(ERROR) 464 << "Failed to associate the job object with a completion port"; 465 return; 466 } 467 468 // Let the main thread know that initialization is complete. 469 caller_task_runner_->PostTask(FROM_HERE, base::Bind( 470 &Core::InitializeJobCompleted, this, base::Passed(&job))); 471 } 472 473 void WtsSessionProcessDelegate::Core::InitializeJobCompleted( 474 scoped_ptr<ScopedHandle> job) { 475 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 476 DCHECK(!job_.IsValid()); 477 478 job_ = job->Pass(); 479 480 if (launch_pending_) 481 DoLaunchProcess(); 482 } 483 484 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() { 485 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 486 487 if (launch_pending_) { 488 LOG(ERROR) << "The worker process exited before connecting via IPC."; 489 launch_pending_ = false; 490 ReportFatalError(); 491 } 492 } 493 494 void WtsSessionProcessDelegate::Core::ReportFatalError() { 495 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 496 497 channel_.reset(); 498 pipe_.Close(); 499 500 WorkerProcessLauncher* event_handler = event_handler_; 501 event_handler_ = NULL; 502 event_handler->OnFatalError(); 503 } 504 505 void WtsSessionProcessDelegate::Core::ReportProcessLaunched( 506 base::win::ScopedHandle worker_process) { 507 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 508 DCHECK(!worker_process_.IsValid()); 509 510 worker_process_ = worker_process.Pass(); 511 512 // Report a handle that can be used to wait for the worker process completion, 513 // query information about the process and duplicate handles. 514 DWORD desired_access = 515 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; 516 HANDLE temp_handle; 517 if (!DuplicateHandle(GetCurrentProcess(), 518 worker_process_, 519 GetCurrentProcess(), 520 &temp_handle, 521 desired_access, 522 FALSE, 523 0)) { 524 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle"; 525 ReportFatalError(); 526 return; 527 } 528 ScopedHandle limited_handle(temp_handle); 529 530 event_handler_->OnProcessLaunched(limited_handle.Pass()); 531 } 532 533 WtsSessionProcessDelegate::WtsSessionProcessDelegate( 534 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 535 scoped_ptr<CommandLine> target_command, 536 bool launch_elevated, 537 const std::string& channel_security) { 538 core_ = new Core(io_task_runner, 539 target_command.Pass(), 540 launch_elevated, 541 channel_security); 542 } 543 544 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() { 545 core_->Stop(); 546 } 547 548 bool WtsSessionProcessDelegate::Initialize(uint32 session_id) { 549 return core_->Initialize(session_id); 550 } 551 552 void WtsSessionProcessDelegate::LaunchProcess( 553 WorkerProcessLauncher* event_handler) { 554 core_->LaunchProcess(event_handler); 555 } 556 557 void WtsSessionProcessDelegate::Send(IPC::Message* message) { 558 core_->Send(message); 559 } 560 561 void WtsSessionProcessDelegate::CloseChannel() { 562 core_->CloseChannel(); 563 } 564 565 void WtsSessionProcessDelegate::KillProcess() { 566 core_->KillProcess(); 567 } 568 569 } // namespace remoting 570