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

Side by Side Diff: sandbox/src/target_process.cc

Issue 9700038: ScopedProcessInformation protects against process/thread handle leaks from CreateProcess calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Touch a previously missed use of PROCESS_INFORMATION Created 8 years, 8 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 #include "sandbox/src/target_process.h" 5 #include "sandbox/src/target_process.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/win/pe_image.h" 9 #include "base/win/pe_image.h"
10 #include "base/win/scoped_process_information.h"
10 #include "sandbox/src/crosscall_server.h" 11 #include "sandbox/src/crosscall_server.h"
11 #include "sandbox/src/crosscall_client.h" 12 #include "sandbox/src/crosscall_client.h"
12 #include "sandbox/src/policy_low_level.h" 13 #include "sandbox/src/policy_low_level.h"
13 #include "sandbox/src/sandbox_types.h" 14 #include "sandbox/src/sandbox_types.h"
14 #include "sandbox/src/sharedmem_ipc_server.h" 15 #include "sandbox/src/sharedmem_ipc_server.h"
15 16
16 namespace { 17 namespace {
17 18
18 void TerminateTarget(PROCESS_INFORMATION* pi) {
19 ::CloseHandle(pi->hThread);
20 ::TerminateProcess(pi->hProcess, 0);
21 ::CloseHandle(pi->hProcess);
22 }
23
24 void CopyPolicyToTarget(const void* source, size_t size, void* dest) { 19 void CopyPolicyToTarget(const void* source, size_t size, void* dest) {
25 if (!source || !size) 20 if (!source || !size)
26 return; 21 return;
27 memcpy(dest, source, size); 22 memcpy(dest, source, size);
28 sandbox::PolicyGlobal* policy = 23 sandbox::PolicyGlobal* policy =
29 reinterpret_cast<sandbox::PolicyGlobal*>(dest); 24 reinterpret_cast<sandbox::PolicyGlobal*>(dest);
30 25
31 size_t offset = reinterpret_cast<size_t>(source); 26 size_t offset = reinterpret_cast<size_t>(source);
32 27
33 for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) { 28 for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 if (shared_section_) 129 if (shared_section_)
135 ::CloseHandle(shared_section_); 130 ::CloseHandle(shared_section_);
136 free(exe_name_); 131 free(exe_name_);
137 } 132 }
138 133
139 // Creates the target (child) process suspended and assigns it to the job 134 // Creates the target (child) process suspended and assigns it to the job
140 // object. 135 // object.
141 DWORD TargetProcess::Create(const wchar_t* exe_path, 136 DWORD TargetProcess::Create(const wchar_t* exe_path,
142 const wchar_t* command_line, 137 const wchar_t* command_line,
143 const wchar_t* desktop, 138 const wchar_t* desktop,
144 PROCESS_INFORMATION* target_info) { 139 PROCESS_INFORMATION* target_info) {
alexeypa (please no reviews) 2012/03/29 04:51:35 target_info can also be converted to ScopedProcess
erikwright (departed) 2012/03/30 17:30:27 Extracted to a new CL, see http://codereview.chrom
145 exe_name_ = _wcsdup(exe_path); 140 exe_name_ = _wcsdup(exe_path);
146 141
147 // the command line needs to be writable by CreateProcess(). 142 // the command line needs to be writable by CreateProcess().
148 scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line)); 143 scoped_ptr_malloc<wchar_t> cmd_line(_wcsdup(command_line));
149 scoped_ptr_malloc<wchar_t> desktop_name(desktop ? _wcsdup(desktop) : NULL); 144 scoped_ptr_malloc<wchar_t> desktop_name(desktop ? _wcsdup(desktop) : NULL);
150 145
151 // Start the target process suspended. 146 // Start the target process suspended.
152 const DWORD flags = CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB | 147 const DWORD flags = CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB |
153 CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; 148 CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS;
154 149
155 STARTUPINFO startup_info = {sizeof(STARTUPINFO)}; 150 STARTUPINFO startup_info = {sizeof(STARTUPINFO)};
156 if (desktop) { 151 if (desktop) {
157 startup_info.lpDesktop = desktop_name.get(); 152 startup_info.lpDesktop = desktop_name.get();
158 } 153 }
159 154
160 PROCESS_INFORMATION process_info = {0}; 155 base::win::ScopedProcessInformation process_info;
161 156
162 if (!::CreateProcessAsUserW(lockdown_token_, 157 if (!::CreateProcessAsUserW(lockdown_token_,
163 exe_path, 158 exe_path,
164 cmd_line.get(), 159 cmd_line.get(),
165 NULL, // No security attribute. 160 NULL, // No security attribute.
166 NULL, // No thread attribute. 161 NULL, // No thread attribute.
167 FALSE, // Do not inherit handles. 162 FALSE, // Do not inherit handles.
168 flags, 163 flags,
169 NULL, // Use the environment of the caller. 164 NULL, // Use the environment of the caller.
170 NULL, // Use current directory of the caller. 165 NULL, // Use current directory of the caller.
171 &startup_info, 166 &startup_info,
172 &process_info)) { 167 process_info.Receive())) {
173 return ::GetLastError(); 168 return ::GetLastError();
174 } 169 }
175 170
176 PoisonLowerAddressRange(process_info.hProcess); 171 PoisonLowerAddressRange(process_info.process_handle());
177 172
178 DWORD win_result = ERROR_SUCCESS; 173 DWORD win_result = ERROR_SUCCESS;
179 174
180 // Assign the suspended target to the windows job object 175 // Assign the suspended target to the windows job object
181 if (!::AssignProcessToJobObject(job_, process_info.hProcess)) { 176 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) {
182 win_result = ::GetLastError(); 177 win_result = ::GetLastError();
183 // It might be a security breach if we let the target run outside the job 178 // It might be a security breach if we let the target run outside the job
184 // so kill it before it causes damage 179 // so kill it before it causes damage
185 TerminateTarget(&process_info); 180 ::TerminateProcess(process_info.process_handle(), 0);
186 return win_result; 181 return win_result;
187 } 182 }
188 183
189 // Change the token of the main thread of the new process for the 184 // Change the token of the main thread of the new process for the
190 // impersonation token with more rights. This allows the target to start; 185 // impersonation token with more rights. This allows the target to start;
191 // otherwise it will crash too early for us to help. 186 // otherwise it will crash too early for us to help.
192 if (!SetThreadToken(&process_info.hThread, initial_token_)) { 187 {
193 win_result = ::GetLastError(); 188 HANDLE temp_thread = process_info.thread_handle();
194 TerminateTarget(&process_info); 189 if (!SetThreadToken(&temp_thread, initial_token_)) {
195 return win_result; 190 win_result = ::GetLastError();
191 ::TerminateProcess(process_info.process_handle(), 0);
192 return win_result;
193 }
196 } 194 }
197 195
198 CONTEXT context; 196 CONTEXT context;
199 context.ContextFlags = CONTEXT_ALL; 197 context.ContextFlags = CONTEXT_ALL;
200 if (!::GetThreadContext(process_info.hThread, &context)) { 198 if (!::GetThreadContext(process_info.thread_handle(), &context)) {
201 win_result = ::GetLastError(); 199 win_result = ::GetLastError();
202 TerminateTarget(&process_info); 200 ::TerminateProcess(process_info.process_handle(), 0);
203 return win_result; 201 return win_result;
204 } 202 }
205 203
206 sandbox_process_ = process_info.hProcess; 204 sandbox_process_ = process_info.process_handle();
207 sandbox_thread_ = process_info.hThread; 205 sandbox_thread_ = process_info.thread_handle();
208 sandbox_process_id_ = process_info.dwProcessId; 206 sandbox_process_id_ = process_info.process_id();
209 207
210 #if defined(_WIN64) 208 #if defined(_WIN64)
211 void* entry_point = reinterpret_cast<void*>(context.Rcx); 209 void* entry_point = reinterpret_cast<void*>(context.Rcx);
212 #else 210 #else
213 #pragma warning(push) 211 #pragma warning(push)
214 #pragma warning(disable: 4312) 212 #pragma warning(disable: 4312)
215 // This cast generates a warning because it is 32 bit specific. 213 // This cast generates a warning because it is 32 bit specific.
216 void* entry_point = reinterpret_cast<void*>(context.Eax); 214 void* entry_point = reinterpret_cast<void*>(context.Eax);
217 #pragma warning(pop) 215 #pragma warning(pop)
218 #endif // _WIN64 216 #endif // _WIN64
219 base_address_ = GetBaseAddress(exe_path, entry_point); 217 base_address_ = GetBaseAddress(exe_path, entry_point);
220 *target_info = process_info; 218 *target_info = process_info.Take();
alexeypa (please no reviews) 2012/03/29 04:51:35 This is an example where Swap semantic could be cl
erikwright (departed) 2012/03/30 17:30:27 See http://codereview.chromium.org/9959018/diff/20
221 return win_result; 219 return win_result;
222 } 220 }
223 221
224 ResultCode TargetProcess::TransferVariable(char* name, void* address, 222 ResultCode TargetProcess::TransferVariable(char* name, void* address,
225 size_t size) { 223 size_t size) {
226 if (NULL == sandbox_process_) 224 if (NULL == sandbox_process_)
227 return SBOX_ERROR_UNEXPECTED_CALL; 225 return SBOX_ERROR_UNEXPECTED_CALL;
228 226
229 void* child_var = address; 227 void* child_var = address;
230 228
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 341
344 342
345 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { 343 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) {
346 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); 344 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL);
347 target->sandbox_process_ = process; 345 target->sandbox_process_ = process;
348 target->base_address_ = base_address; 346 target->base_address_ = base_address;
349 return target; 347 return target;
350 } 348 }
351 349
352 } // namespace sandbox 350 } // namespace sandbox
OLDNEW
« base/win/scoped_process_information_unittest.cc ('K') | « sandbox/src/restricted_token_utils.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698