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

Unified Diff: remoting/host/win/wts_session_process_delegate.cc

Issue 2446053002: Use ChannelMojo between the remoting daemon and desktop processes. (Closed)
Patch Set: Created 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/switches.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/win/wts_session_process_delegate.cc
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
index 7469d5d74fc9a931d8d241ff7865c2b500c0e918..b0bc149505b67e58b76a51416344255c75fe7fd9 100644
--- a/remoting/host/win/wts_session_process_delegate.cc
+++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -24,9 +25,13 @@
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_message.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/named_platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "remoting/host/host_main.h"
#include "remoting/host/ipc_constants.h"
-#include "remoting/host/ipc_util.h"
#include "remoting/host/switches.h"
#include "remoting/host/win/launch_process_with_token.h"
#include "remoting/host/win/security_descriptor.h"
@@ -101,8 +106,12 @@ class WtsSessionProcessDelegate::Core
// Called when the number of processes running in the job reaches zero.
void OnActiveProcessZero();
+ // Called when a process is launched in |job_|.
+ void OnProcessLaunchDetected(base::ProcessId pid);
+
void ReportFatalError();
- void ReportProcessLaunched(base::win::ScopedHandle worker_process);
+ void ReportProcessLaunched(base::win::ScopedHandle worker_process,
+ mojo::edk::ScopedPlatformHandle server_handle);
// The task runner all public methods of this class should be called on.
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
@@ -122,10 +131,6 @@ class WtsSessionProcessDelegate::Core
WorkerProcessLauncher* event_handler_;
- // Pointer to GetNamedPipeClientProcessId() API if it is available.
- typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*);
- GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_;
-
// The job object used to control the lifetime of child processes.
base::win::ScopedHandle job_;
@@ -135,9 +140,6 @@ class WtsSessionProcessDelegate::Core
// True if a laucnh attemp is pending.
bool launch_pending_;
- // The named pipe used as the transport by |channel_|.
- base::win::ScopedHandle pipe_;
-
// The token to be used to launch a process in a different session.
base::win::ScopedHandle session_token_;
@@ -147,6 +149,16 @@ class WtsSessionProcessDelegate::Core
// The handle of the worker process, if launched.
base::win::ScopedHandle worker_process_;
+ // If launching elevated, this holds the server handle after launch, until
+ // the final process launches.
+ mojo::edk::ScopedPlatformHandle elevated_server_handle_;
+
+ // If launching elevated, this is the pid of the launcher process.
+ base::ProcessId elevated_launcher_pid_ = base::kNullProcessId;
+
+ // The mojo child token for the process being launched.
+ std::string mojo_child_token_;
+
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -161,7 +173,6 @@ WtsSessionProcessDelegate::Core::Core(
channel_security_(channel_security),
new_process_security_(new_process_security),
event_handler_(nullptr),
- get_named_pipe_client_pid_(nullptr),
launch_elevated_(launch_elevated),
launch_pending_(false),
target_command_(std::move(target_command)) {}
@@ -174,11 +185,6 @@ bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) {
HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll");
CHECK(kernel32 != nullptr);
- get_named_pipe_client_pid_ =
- reinterpret_cast<GetNamedPipeClientProcessIdFn>(
- GetProcAddress(kernel32, "GetNamedPipeClientProcessId"));
- CHECK(get_named_pipe_client_pid_ != nullptr);
-
ScopedHandle job;
job.Set(CreateJobObject(nullptr, nullptr));
if (!job.IsValid()) {
@@ -253,7 +259,12 @@ void WtsSessionProcessDelegate::Core::CloseChannel() {
IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
channel_.get());
channel_.reset();
- pipe_.Close();
+ elevated_server_handle_.reset();
+ elevated_launcher_pid_ = base::kNullProcessId;
+ if (!mojo_child_token_.empty()) {
+ mojo::edk::ChildProcessLaunchFailed(mojo_child_token_);
+ mojo_child_token_.clear();
+ }
}
void WtsSessionProcessDelegate::Core::KillProcess() {
@@ -278,7 +289,6 @@ void WtsSessionProcessDelegate::Core::KillProcess() {
WtsSessionProcessDelegate::Core::~Core() {
DCHECK(!channel_);
DCHECK(!event_handler_);
- DCHECK(!pipe_.IsValid());
DCHECK(!worker_process_.IsValid());
}
@@ -290,9 +300,18 @@ void WtsSessionProcessDelegate::Core::OnIOCompleted(
// |bytes_transferred| is used in job object notifications to supply
// the message ID; |context| carries process ID.
- if (bytes_transferred == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
- caller_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Core::OnActiveProcessZero, this));
+ switch (bytes_transferred) {
+ case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: {
+ caller_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Core::OnActiveProcessZero, this));
+ break;
+ }
+ case JOB_OBJECT_MSG_NEW_PROCESS: {
+ caller_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
+ reinterpret_cast<base::ProcessId>(context)));
+ break;
+ }
}
}
@@ -306,37 +325,6 @@ bool WtsSessionProcessDelegate::Core::OnMessageReceived(
void WtsSessionProcessDelegate::Core::OnChannelConnected(int32_t peer_pid) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
- // Report the worker PID now if the worker process is launched indirectly.
- // Note that in this case the pipe's security descriptor is the only
- // protection against a malicious processed connecting to the pipe.
- if (launch_elevated_) {
- DWORD pid;
- if (!get_named_pipe_client_pid_(pipe_.Get(), &pid)) {
- PLOG(ERROR) << "Failed to retrive PID of the client";
- ReportFatalError();
- return;
- }
-
- if (pid != static_cast<DWORD>(peer_pid)) {
- LOG(ERROR) << "The actual client PID " << pid
- << " does not match the one reported by the client: "
- << peer_pid;
- ReportFatalError();
- return;
- }
-
- DWORD desired_access =
- SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
- ScopedHandle worker_process(OpenProcess(desired_access, false, pid));
- if (!worker_process.IsValid()) {
- PLOG(ERROR) << "Failed to open process " << pid;
- ReportFatalError();
- return;
- }
-
- ReportProcessLaunched(std::move(worker_process));
- }
-
if (event_handler_)
event_handler_->OnChannelConnected(peer_pid);
}
@@ -350,7 +338,6 @@ void WtsSessionProcessDelegate::Core::OnChannelError() {
void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DCHECK(!channel_);
- DCHECK(!pipe_.IsValid());
DCHECK(!worker_process_.IsValid());
base::CommandLine command_line(target_command_->argv());
@@ -375,25 +362,34 @@ void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
target_command_->GetProgram());
}
- // Create the server end of the IPC channel.
- std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID();
- ScopedHandle pipe;
- if (!CreateIpcChannel(channel_name, channel_security_, &pipe)) {
- ReportFatalError();
- return;
- }
-
- // Wrap the pipe into an IPC channel.
+ const std::string mojo_message_pipe_token = mojo::edk::GenerateRandomToken();
+ mojo_child_token_ = mojo::edk::GenerateRandomToken();
std::unique_ptr<IPC::ChannelProxy> channel(
new IPC::ChannelProxy(this, io_task_runner_));
IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
channel.get(), io_task_runner_);
- channel->Init(IPC::ChannelHandle(pipe.Get()), IPC::Channel::MODE_SERVER,
- /*create_pipe_now=*/true);
-
- // Pass the name of the IPC channel to use.
- command_line.AppendSwitchNative(kDaemonPipeSwitchName,
- base::UTF8ToWide(channel_name));
+ channel->Init(mojo::edk::CreateParentMessagePipe(mojo_message_pipe_token,
+ mojo_child_token_)
+ .release(),
+ IPC::Channel::MODE_SERVER, /*create_pipe_now=*/true);
+ command_line.AppendSwitchASCII(kMojoPipeToken, mojo_message_pipe_token);
+
+ std::unique_ptr<mojo::edk::PlatformChannelPair> normal_mojo_channel;
+ std::unique_ptr<mojo::edk::NamedPlatformChannelPair> elevated_mojo_channel;
+ base::HandlesToInheritVector handles_to_inherit;
+ if (launch_elevated_) {
+ // Pass the name of the IPC channel to use.
+ mojo::edk::NamedPlatformChannelPair::Options options;
+ options.security_descriptor = base::UTF8ToUTF16(channel_security_);
+ elevated_mojo_channel =
+ base::MakeUnique<mojo::edk::NamedPlatformChannelPair>(options);
+ elevated_mojo_channel->PrepareToPassClientHandleToChildProcess(
+ &command_line);
+ } else {
+ normal_mojo_channel = base::MakeUnique<mojo::edk::PlatformChannelPair>();
+ normal_mojo_channel->PrepareToPassClientHandleToChildProcess(
+ &command_line, &handles_to_inherit);
+ }
ScopedSd security_descriptor;
std::unique_ptr<SECURITY_ATTRIBUTES> security_attributes;
@@ -417,7 +413,7 @@ void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
if (!LaunchProcessWithToken(
command_line.GetProgram(), command_line.GetCommandLineString(),
session_token_.Get(), security_attributes.get(),
- /* thread_attributes= */ nullptr, /* handles_to_inherit=*/{},
+ /* thread_attributes= */ nullptr, handles_to_inherit,
/* creation_flags= */ CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
base::UTF8ToUTF16(kDefaultDesktopName).c_str(), &worker_process,
&worker_thread)) {
@@ -440,13 +436,19 @@ void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
}
channel_ = std::move(channel);
- pipe_ = std::move(pipe);
- // Report success if the worker process is lauched directly. Otherwise, PID of
- // the client connected to the pipe will be used later. See
- // OnChannelConnected().
- if (!launch_elevated_)
- ReportProcessLaunched(std::move(worker_process));
+ if (launch_elevated_) {
+ // When launching an elevated worker process, an intermediate launcher
+ // process launches the worker process. Reporting the launch waits until the
+ // worker process launch is detected. Until then, store the values needed in
+ // fields. See OnProcessLaunchDetected for their use.
+ elevated_server_handle_ = elevated_mojo_channel->PassServerHandle();
+ elevated_launcher_pid_ = GetProcessId(worker_process.Get());
+ DCHECK(elevated_server_handle_.is_valid());
+ } else {
+ ReportProcessLaunched(std::move(worker_process),
+ normal_mojo_channel->PassServerHandle());
+ }
}
void WtsSessionProcessDelegate::Core::DrainJobNotifications() {
@@ -506,6 +508,29 @@ void WtsSessionProcessDelegate::Core::OnActiveProcessZero() {
}
}
+void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected(
+ base::ProcessId pid) {
+ DCHECK(caller_task_runner_->BelongsToCurrentThread());
+ if (!elevated_server_handle_.is_valid())
+ return;
+
+ if (pid == elevated_launcher_pid_)
+ return;
+
+ DWORD desired_access =
+ SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
+ base::win::ScopedHandle worker_process(
+ OpenProcess(desired_access, false, pid));
+ if (!worker_process.IsValid()) {
+ PLOG(ERROR) << "Failed to open process " << pid;
+ ReportFatalError();
+ return;
+ }
+ elevated_launcher_pid_ = base::kNullProcessId;
+ ReportProcessLaunched(std::move(worker_process),
+ std::move(elevated_server_handle_));
+}
+
void WtsSessionProcessDelegate::Core::ReportFatalError() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
@@ -517,10 +542,15 @@ void WtsSessionProcessDelegate::Core::ReportFatalError() {
}
void WtsSessionProcessDelegate::Core::ReportProcessLaunched(
- base::win::ScopedHandle worker_process) {
+ base::win::ScopedHandle worker_process,
+ mojo::edk::ScopedPlatformHandle server_handle) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DCHECK(!worker_process_.IsValid());
+ mojo::edk::ChildProcessLaunched(worker_process.Get(),
+ std::move(server_handle),
+ mojo_child_token_);
+ mojo_child_token_.clear();
worker_process_ = std::move(worker_process);
// Report a handle that can be used to wait for the worker process completion,
« no previous file with comments | « remoting/host/switches.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698