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

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: CR feedback. 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"
19 #include "remoting/host/ipc_consts.h"
16 #include "remoting/host/win/launch_process_with_token.h" 20 #include "remoting/host/win/launch_process_with_token.h"
17 21
18 using base::win::ScopedHandle; 22 using base::win::ScopedHandle;
19 23
20 namespace { 24 namespace {
21 25
22 // The command line switch specifying the name of the daemon IPC endpoint. 26 // The security descriptor used to protect the named pipe in between
23 const char kDaemonIpcSwitchName[] = "daemon-pipe"; 27 // CreateNamedPipe() and CreateFile() calls before it will be passed to
28 // the network process. It gives full access to LocalSystem and denies access by
29 // anyone else.
30 const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)";
24 31
25 // The command line parameters that should be copied from the service's command 32 // The command line parameters that should be copied from the service's command
26 // line to the host process. 33 // line to the host process.
27 const char* kCopiedSwitchNames[] = { 34 const char* kCopiedSwitchNames[] = {
28 "host-config", switches::kV, switches::kVModule }; 35 "host-config", switches::kV, switches::kVModule };
29 36
30 } // namespace 37 } // namespace
31 38
32 namespace remoting { 39 namespace remoting {
33 40
34 UnprivilegedProcessDelegate::UnprivilegedProcessDelegate( 41 UnprivilegedProcessDelegate::UnprivilegedProcessDelegate(
35 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 42 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
36 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 43 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
37 const FilePath& binary_path) 44 const FilePath& binary_path)
38 : main_task_runner_(main_task_runner), 45 : main_task_runner_(main_task_runner),
39 io_task_runner_(io_task_runner), 46 io_task_runner_(io_task_runner),
40 binary_path_(binary_path) { 47 binary_path_(binary_path) {
41 } 48 }
42 49
43 UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() { 50 UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() {
44 KillProcess(CONTROL_C_EXIT); 51 KillProcess(CONTROL_C_EXIT);
45 } 52 }
46 53
54 bool UnprivilegedProcessDelegate::Send(IPC::Message* message) {
55 DCHECK(main_task_runner_->BelongsToCurrentThread());
56
57 return channel_->Send(message);
58 }
59
47 DWORD UnprivilegedProcessDelegate::GetExitCode() { 60 DWORD UnprivilegedProcessDelegate::GetExitCode() {
48 DCHECK(main_task_runner_->BelongsToCurrentThread()); 61 DCHECK(main_task_runner_->BelongsToCurrentThread());
49 62
50 DWORD exit_code = CONTROL_C_EXIT; 63 DWORD exit_code = CONTROL_C_EXIT;
51 if (worker_process_.IsValid()) { 64 if (worker_process_.IsValid()) {
52 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { 65 if (!::GetExitCodeProcess(worker_process_, &exit_code)) {
53 LOG_GETLASTERROR(INFO) 66 LOG_GETLASTERROR(INFO)
54 << "Failed to query the exit code of the worker process"; 67 << "Failed to query the exit code of the worker process";
55 exit_code = CONTROL_C_EXIT; 68 exit_code = CONTROL_C_EXIT;
56 } 69 }
57 } 70 }
58 71
59 return exit_code; 72 return exit_code;
60 } 73 }
61 74
62 void UnprivilegedProcessDelegate::KillProcess(DWORD exit_code) { 75 void UnprivilegedProcessDelegate::KillProcess(DWORD exit_code) {
63 DCHECK(main_task_runner_->BelongsToCurrentThread()); 76 DCHECK(main_task_runner_->BelongsToCurrentThread());
64 77
78 channel_.reset();
79
65 if (worker_process_.IsValid()) { 80 if (worker_process_.IsValid()) {
66 TerminateProcess(worker_process_, exit_code); 81 TerminateProcess(worker_process_, exit_code);
67 } 82 }
68 } 83 }
69 84
70 bool UnprivilegedProcessDelegate::LaunchProcess( 85 bool UnprivilegedProcessDelegate::LaunchProcess(
71 const std::string& channel_name, 86 IPC::Listener* delegate,
72 ScopedHandle* process_exit_event_out) { 87 ScopedHandle* process_exit_event_out) {
73 DCHECK(main_task_runner_->BelongsToCurrentThread()); 88 DCHECK(main_task_runner_->BelongsToCurrentThread());
89 // Generate a unique name for the channel.
90 std::string channel_name = GenerateIpcChannelName(this);
91
92 // Create a connected IPC channel.
93 ScopedHandle client;
94 scoped_ptr<IPC::ChannelProxy> server;
95 if (!CreateConnectedIpcChannel(channel_name, delegate, &client, &server))
96 return false;
97
98 // Convert the handle value into a decimal integer. Handle values are 32bit
99 // even on 64bit platforms.
100 std::string pipe_handle = base::StringPrintf(
101 "%d", reinterpret_cast<ULONG_PTR>(client.Get()));
74 102
75 // Create the command line passing the name of the IPC channel to use and 103 // Create the command line passing the name of the IPC channel to use and
76 // copying known switches from the caller's command line. 104 // copying known switches from the caller's command line.
77 CommandLine command_line(binary_path_); 105 CommandLine command_line(binary_path_);
78 command_line.AppendSwitchNative(kDaemonIpcSwitchName, 106 command_line.AppendSwitchASCII(kDaemonPipeSwitchName, pipe_handle);
79 UTF8ToWide(channel_name));
80 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 107 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
81 kCopiedSwitchNames, 108 kCopiedSwitchNames,
82 arraysize(kCopiedSwitchNames)); 109 arraysize(kCopiedSwitchNames));
83 110
84 // Try to launch the process. 111 // Try to launch the process.
85 // TODO(alexeypa): Pass a restricted process token. 112 // TODO(alexeypa): Pass a restricted process token.
86 // See http://crbug.com/134694. 113 // See http://crbug.com/134694.
87 ScopedHandle worker_thread; 114 ScopedHandle worker_thread;
88 worker_process_.Close(); 115 worker_process_.Close();
89 if (!LaunchProcessWithToken(command_line.GetProgram(), 116 if (!LaunchProcessWithToken(command_line.GetProgram(),
90 command_line.GetCommandLineString(), 117 command_line.GetCommandLineString(),
91 NULL, 118 NULL,
119 true,
92 0, 120 0,
93 &worker_process_, 121 &worker_process_,
94 &worker_thread)) { 122 &worker_thread)) {
95 return false; 123 return false;
96 } 124 }
97 125
98 // Return a handle that the caller can wait on to get notified when 126 // Return a handle that the caller can wait on to get notified when
99 // the process terminates. 127 // the process terminates.
100 ScopedHandle process_exit_event; 128 ScopedHandle process_exit_event;
101 if (!DuplicateHandle(GetCurrentProcess(), 129 if (!DuplicateHandle(GetCurrentProcess(),
102 worker_process_, 130 worker_process_,
103 GetCurrentProcess(), 131 GetCurrentProcess(),
104 process_exit_event.Receive(), 132 process_exit_event.Receive(),
105 SYNCHRONIZE, 133 SYNCHRONIZE,
106 FALSE, 134 FALSE,
107 0)) { 135 0)) {
108 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle"; 136 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle";
109 KillProcess(CONTROL_C_EXIT); 137 KillProcess(CONTROL_C_EXIT);
110 return false; 138 return false;
111 } 139 }
112 140
141 channel_ = server.Pass();
113 *process_exit_event_out = process_exit_event.Pass(); 142 *process_exit_event_out = process_exit_event.Pass();
114 return true; 143 return true;
115 } 144 }
116 145
146 bool UnprivilegedProcessDelegate::CreateConnectedIpcChannel(
147 const std::string& channel_name,
148 IPC::Listener* delegate,
149 ScopedHandle* client_out,
150 scoped_ptr<IPC::ChannelProxy>* server_out) {
151 // Create the server end of the channel.
152 scoped_ptr<IPC::ChannelProxy> server;
153 if (!CreateIpcChannel(channel_name, kDaemonIpcSecurityDescriptor,
154 io_task_runner_, delegate, &server)) {
155 return false;
156 }
157
158 // Convert the channel name to the pipe name.
159 std::string pipe_name(kChromePipeNamePrefix);
160 pipe_name.append(channel_name);
161
162 SECURITY_ATTRIBUTES security_attributes;
163 security_attributes.nLength = sizeof(security_attributes);
164 security_attributes.lpSecurityDescriptor = NULL;
165 security_attributes.bInheritHandle = TRUE;
166
167 // Create the client end of the channel. This code should match the code in
168 // IPC::Channel.
169 ScopedHandle client;
170 client.Set(CreateFile(UTF8ToUTF16(pipe_name).c_str(),
171 GENERIC_READ | GENERIC_WRITE,
172 0,
173 &security_attributes,
174 OPEN_EXISTING,
175 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
176 FILE_FLAG_OVERLAPPED,
177 NULL));
178 if (!client.IsValid())
179 return false;
180
181 *client_out = client.Pass();
182 *server_out = server.Pass();
183 return true;
184 }
185
117 } // namespace remoting 186 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/win/unprivileged_process_delegate.h ('k') | remoting/host/win/worker_process_launcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698