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.
5 #include "base/process_util.h"
15 #include "base/bind.h"
16 #include "base/bind_helpers.h"
17 #include "base/command_line.h"
18 #include "base/debug/stack_trace.h"
19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop.h"
22 #include "base/metrics/histogram.h"
23 #include "base/sys_info.h"
24 #include "base/win/object_watcher.h"
25 #include "base/win/scoped_handle.h"
26 #include "base/win/scoped_process_information.h"
27 #include "base/win/windows_version.h"
29 // userenv.dll is required for CreateEnvironmentBlock().
30 #pragma comment(lib, "userenv.lib")
36 // Exit codes with special meanings on Windows.
37 const DWORD kNormalTerminationExitCode
= 0;
38 const DWORD kDebuggerInactiveExitCode
= 0xC0000354;
39 const DWORD kKeyboardInterruptExitCode
= 0xC000013A;
40 const DWORD kDebuggerTerminatedExitCode
= 0x40010004;
42 // Maximum amount of time (in milliseconds) to wait for the process to exit.
43 static const int kWaitInterval
= 2000;
45 // This exit code is used by the Windows task manager when it kills a
46 // process. It's value is obviously not that unique, and it's
47 // surprising to me that the task manager uses this value, but it
48 // seems to be common practice on Windows to test for it as an
49 // indication that the task manager has killed something if the
51 const DWORD kProcessKilledExitCode
= 1;
53 // HeapSetInformation function pointer.
54 typedef BOOL (WINAPI
* HeapSetFn
)(HANDLE
, HEAP_INFORMATION_CLASS
, PVOID
, SIZE_T
);
57 // Kill the process. This is important for security, since WebKit doesn't
58 // NULL-check many memory allocations. If a malloc fails, returns NULL, and
59 // the buffer is then used, it provides a handy mapping of memory starting at
60 // address 0 for an attacker to utilize.
65 class TimerExpiredTask
: public win::ObjectWatcher::Delegate
{
67 explicit TimerExpiredTask(ProcessHandle process
);
72 // MessageLoop::Watcher -----------------------------------------------------
73 virtual void OnObjectSignaled(HANDLE object
);
78 // The process that we are watching.
79 ProcessHandle process_
;
81 win::ObjectWatcher watcher_
;
83 DISALLOW_COPY_AND_ASSIGN(TimerExpiredTask
);
86 TimerExpiredTask::TimerExpiredTask(ProcessHandle process
) : process_(process
) {
87 watcher_
.StartWatching(process_
, this);
90 TimerExpiredTask::~TimerExpiredTask() {
92 DCHECK(!process_
) << "Make sure to close the handle.";
95 void TimerExpiredTask::TimedOut() {
100 void TimerExpiredTask::OnObjectSignaled(HANDLE object
) {
101 CloseHandle(process_
);
105 void TimerExpiredTask::KillProcess() {
106 // Stop watching the process handle since we're killing it.
107 watcher_
.StopWatching();
109 // OK, time to get frisky. We don't actually care when the process
110 // terminates. We just care that it eventually terminates, and that's what
111 // TerminateProcess should do for us. Don't check for the result code since
112 // it fails quite often. This should be investigated eventually.
113 base::KillProcess(process_
, kProcessKilledExitCode
, false);
115 // Now, just cleanup as if the process exited normally.
116 OnObjectSignaled(process_
);
121 void RouteStdioToConsole() {
122 // Don't change anything if stdout or stderr already point to a
125 // If we are running under Buildbot or under Cygwin's default
126 // terminal (mintty), stderr and stderr will be pipe handles. In
127 // that case, we don't want to open CONOUT$, because its output
128 // likely does not go anywhere.
130 // We don't use GetStdHandle() to check stdout/stderr here because
131 // it can return dangling IDs of handles that were never inherited
132 // by this process. These IDs could have been reused by the time
133 // this function is called. The CRT checks the validity of
134 // stdout/stderr on startup (before the handle IDs can be reused).
135 // _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
137 if (_fileno(stdout
) >= 0 || _fileno(stderr
) >= 0)
140 if (!AttachConsole(ATTACH_PARENT_PROCESS
)) {
141 unsigned int result
= GetLastError();
142 // Was probably already attached.
143 if (result
== ERROR_ACCESS_DENIED
)
145 // Don't bother creating a new console for each child process if the
146 // parent process is invalid (eg: crashed).
147 if (result
== ERROR_GEN_FAILURE
)
149 // Make a new console if attaching to parent fails with any other error.
150 // It should be ERROR_INVALID_HANDLE at this point, which means the browser
151 // was likely not started from a console.
155 // Arbitrary byte count to use when buffering output lines. More
156 // means potential waste, less means more risk of interleaved
157 // log-lines in output.
158 enum { kOutputBufferSize
= 64 * 1024 };
160 if (freopen("CONOUT$", "w", stdout
)) {
161 setvbuf(stdout
, NULL
, _IOLBF
, kOutputBufferSize
);
162 // Overwrite FD 1 for the benefit of any code that uses this FD
163 // directly. This is safe because the CRT allocates FDs 0, 1 and
164 // 2 at startup even if they don't have valid underlying Windows
165 // handles. This means we won't be overwriting an FD created by
166 // _open() after startup.
167 _dup2(_fileno(stdout
), 1);
169 if (freopen("CONOUT$", "w", stderr
)) {
170 setvbuf(stderr
, NULL
, _IOLBF
, kOutputBufferSize
);
171 _dup2(_fileno(stderr
), 2);
174 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog.
175 std::ios::sync_with_stdio();
178 ProcessId
GetCurrentProcId() {
179 return ::GetCurrentProcessId();
182 ProcessHandle
GetCurrentProcessHandle() {
183 return ::GetCurrentProcess();
186 HMODULE
GetModuleFromAddress(void* address
) {
187 HMODULE instance
= NULL
;
188 if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
189 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
,
190 static_cast<char*>(address
),
197 bool OpenProcessHandle(ProcessId pid
, ProcessHandle
* handle
) {
198 // We try to limit privileges granted to the handle. If you need this
199 // for test code, consider using OpenPrivilegedProcessHandle instead of
200 // adding more privileges here.
201 ProcessHandle result
= OpenProcess(PROCESS_TERMINATE
|
202 PROCESS_QUERY_INFORMATION
|
213 bool OpenPrivilegedProcessHandle(ProcessId pid
, ProcessHandle
* handle
) {
214 ProcessHandle result
= OpenProcess(PROCESS_DUP_HANDLE
|
216 PROCESS_QUERY_INFORMATION
|
228 bool OpenProcessHandleWithAccess(ProcessId pid
,
230 ProcessHandle
* handle
) {
231 ProcessHandle result
= OpenProcess(access_flags
, FALSE
, pid
);
240 void CloseProcessHandle(ProcessHandle process
) {
241 CloseHandle(process
);
244 ProcessId
GetProcId(ProcessHandle process
) {
245 // Get a handle to |process| that has PROCESS_QUERY_INFORMATION rights.
246 HANDLE current_process
= GetCurrentProcess();
247 HANDLE process_with_query_rights
;
248 if (DuplicateHandle(current_process
, process
, current_process
,
249 &process_with_query_rights
, PROCESS_QUERY_INFORMATION
,
251 DWORD id
= GetProcessId(process_with_query_rights
);
252 CloseHandle(process_with_query_rights
);
261 bool GetProcessIntegrityLevel(ProcessHandle process
, IntegrityLevel
*level
) {
265 if (win::GetVersion() < base::win::VERSION_VISTA
)
268 HANDLE process_token
;
269 if (!OpenProcessToken(process
, TOKEN_QUERY
| TOKEN_QUERY_SOURCE
,
273 win::ScopedHandle
scoped_process_token(process_token
);
275 DWORD token_info_length
= 0;
276 if (GetTokenInformation(process_token
, TokenIntegrityLevel
, NULL
, 0,
277 &token_info_length
) ||
278 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
281 scoped_ptr
<char[]> token_label_bytes(new char[token_info_length
]);
282 if (!token_label_bytes
.get())
285 TOKEN_MANDATORY_LABEL
* token_label
=
286 reinterpret_cast<TOKEN_MANDATORY_LABEL
*>(token_label_bytes
.get());
290 if (!GetTokenInformation(process_token
, TokenIntegrityLevel
, token_label
,
291 token_info_length
, &token_info_length
))
294 DWORD integrity_level
= *GetSidSubAuthority(token_label
->Label
.Sid
,
295 (DWORD
)(UCHAR
)(*GetSidSubAuthorityCount(token_label
->Label
.Sid
)-1));
297 if (integrity_level
< SECURITY_MANDATORY_MEDIUM_RID
) {
298 *level
= LOW_INTEGRITY
;
299 } else if (integrity_level
>= SECURITY_MANDATORY_MEDIUM_RID
&&
300 integrity_level
< SECURITY_MANDATORY_HIGH_RID
) {
301 *level
= MEDIUM_INTEGRITY
;
302 } else if (integrity_level
>= SECURITY_MANDATORY_HIGH_RID
) {
303 *level
= HIGH_INTEGRITY
;
312 bool LaunchProcess(const string16
& cmdline
,
313 const LaunchOptions
& options
,
314 ProcessHandle
* process_handle
) {
315 STARTUPINFO startup_info
= {};
316 startup_info
.cb
= sizeof(startup_info
);
317 if (options
.empty_desktop_name
)
318 startup_info
.lpDesktop
= L
"";
319 startup_info
.dwFlags
= STARTF_USESHOWWINDOW
;
320 startup_info
.wShowWindow
= options
.start_hidden
? SW_HIDE
: SW_SHOW
;
322 if (options
.stdin_handle
|| options
.stdout_handle
|| options
.stderr_handle
) {
323 DCHECK(options
.inherit_handles
);
324 DCHECK(options
.stdin_handle
);
325 DCHECK(options
.stdout_handle
);
326 DCHECK(options
.stderr_handle
);
327 startup_info
.dwFlags
|= STARTF_USESTDHANDLES
;
328 startup_info
.hStdInput
= options
.stdin_handle
;
329 startup_info
.hStdOutput
= options
.stdout_handle
;
330 startup_info
.hStdError
= options
.stderr_handle
;
335 if (options
.job_handle
) {
336 flags
|= CREATE_SUSPENDED
;
338 // If this code is run under a debugger, the launched process is
339 // automatically associated with a job object created by the debugger.
340 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this.
341 flags
|= CREATE_BREAKAWAY_FROM_JOB
;
344 if (options
.force_breakaway_from_job_
)
345 flags
|= CREATE_BREAKAWAY_FROM_JOB
;
347 base::win::ScopedProcessInformation process_info
;
349 if (options
.as_user
) {
350 flags
|= CREATE_UNICODE_ENVIRONMENT
;
351 void* enviroment_block
= NULL
;
353 if (!CreateEnvironmentBlock(&enviroment_block
, options
.as_user
, FALSE
)) {
359 CreateProcessAsUser(options
.as_user
, NULL
,
360 const_cast<wchar_t*>(cmdline
.c_str()),
361 NULL
, NULL
, options
.inherit_handles
, flags
,
362 enviroment_block
, NULL
, &startup_info
,
363 process_info
.Receive());
364 DestroyEnvironmentBlock(enviroment_block
);
370 if (!CreateProcess(NULL
,
371 const_cast<wchar_t*>(cmdline
.c_str()), NULL
, NULL
,
372 options
.inherit_handles
, flags
, NULL
, NULL
,
373 &startup_info
, process_info
.Receive())) {
379 if (options
.job_handle
) {
380 if (0 == AssignProcessToJobObject(options
.job_handle
,
381 process_info
.process_handle())) {
382 DLOG(ERROR
) << "Could not AssignProcessToObject.";
383 KillProcess(process_info
.process_handle(), kProcessKilledExitCode
, true);
387 ResumeThread(process_info
.thread_handle());
391 WaitForSingleObject(process_info
.process_handle(), INFINITE
);
393 // If the caller wants the process handle, we won't close it.
395 *process_handle
= process_info
.TakeProcessHandle();
400 bool LaunchProcess(const CommandLine
& cmdline
,
401 const LaunchOptions
& options
,
402 ProcessHandle
* process_handle
) {
403 return LaunchProcess(cmdline
.GetCommandLineString(), options
, process_handle
);
406 bool SetJobObjectAsKillOnJobClose(HANDLE job_object
) {
407 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info
= {0};
408 limit_info
.BasicLimitInformation
.LimitFlags
=
409 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
;
410 return 0 != SetInformationJobObject(
412 JobObjectExtendedLimitInformation
,
417 // Attempts to kill the process identified by the given process
418 // entry structure, giving it the specified exit code.
419 // Returns true if this is successful, false otherwise.
420 bool KillProcessById(ProcessId process_id
, int exit_code
, bool wait
) {
421 HANDLE process
= OpenProcess(PROCESS_TERMINATE
| SYNCHRONIZE
,
422 FALSE
, // Don't inherit handle
425 DLOG_GETLASTERROR(ERROR
) << "Unable to open process " << process_id
;
428 bool ret
= KillProcess(process
, exit_code
, wait
);
429 CloseHandle(process
);
433 bool GetAppOutput(const CommandLine
& cl
, std::string
* output
) {
434 HANDLE out_read
= NULL
;
435 HANDLE out_write
= NULL
;
437 SECURITY_ATTRIBUTES sa_attr
;
438 // Set the bInheritHandle flag so pipe handles are inherited.
439 sa_attr
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
440 sa_attr
.bInheritHandle
= TRUE
;
441 sa_attr
.lpSecurityDescriptor
= NULL
;
443 // Create the pipe for the child process's STDOUT.
444 if (!CreatePipe(&out_read
, &out_write
, &sa_attr
, 0)) {
445 NOTREACHED() << "Failed to create pipe";
449 // Ensure we don't leak the handles.
450 win::ScopedHandle
scoped_out_read(out_read
);
451 win::ScopedHandle
scoped_out_write(out_write
);
453 // Ensure the read handle to the pipe for STDOUT is not inherited.
454 if (!SetHandleInformation(out_read
, HANDLE_FLAG_INHERIT
, 0)) {
455 NOTREACHED() << "Failed to disabled pipe inheritance";
459 FilePath::StringType
writable_command_line_string(cl
.GetCommandLineString());
461 base::win::ScopedProcessInformation proc_info
;
462 STARTUPINFO start_info
= { 0 };
464 start_info
.cb
= sizeof(STARTUPINFO
);
465 start_info
.hStdOutput
= out_write
;
466 // Keep the normal stdin and stderr.
467 start_info
.hStdInput
= GetStdHandle(STD_INPUT_HANDLE
);
468 start_info
.hStdError
= GetStdHandle(STD_ERROR_HANDLE
);
469 start_info
.dwFlags
|= STARTF_USESTDHANDLES
;
471 // Create the child process.
472 if (!CreateProcess(NULL
,
473 &writable_command_line_string
[0],
475 TRUE
, // Handles are inherited.
476 0, NULL
, NULL
, &start_info
, proc_info
.Receive())) {
477 NOTREACHED() << "Failed to start process";
481 // Close our writing end of pipe now. Otherwise later read would not be able
482 // to detect end of child's output.
483 scoped_out_write
.Close();
485 // Read output from the child process's pipe for STDOUT
486 const int kBufferSize
= 1024;
487 char buffer
[kBufferSize
];
490 DWORD bytes_read
= 0;
491 BOOL success
= ReadFile(out_read
, buffer
, kBufferSize
, &bytes_read
, NULL
);
492 if (!success
|| bytes_read
== 0)
494 output
->append(buffer
, bytes_read
);
497 // Let's wait for the process to finish.
498 WaitForSingleObject(proc_info
.process_handle(), INFINITE
);
503 bool KillProcess(ProcessHandle process
, int exit_code
, bool wait
) {
504 bool result
= (TerminateProcess(process
, exit_code
) != FALSE
);
505 if (result
&& wait
) {
506 // The process may not end immediately due to pending I/O
507 if (WAIT_OBJECT_0
!= WaitForSingleObject(process
, 60 * 1000))
508 DLOG_GETLASTERROR(ERROR
) << "Error waiting for process exit";
509 } else if (!result
) {
510 DLOG_GETLASTERROR(ERROR
) << "Unable to terminate process";
515 TerminationStatus
GetTerminationStatus(ProcessHandle handle
, int* exit_code
) {
516 DWORD tmp_exit_code
= 0;
518 if (!::GetExitCodeProcess(handle
, &tmp_exit_code
)) {
519 DLOG_GETLASTERROR(FATAL
) << "GetExitCodeProcess() failed";
521 // This really is a random number. We haven't received any
522 // information about the exit code, presumably because this
523 // process doesn't have permission to get the exit code, or
524 // because of some other cause for GetExitCodeProcess to fail
525 // (MSDN docs don't give the possible failure error codes for
526 // this function, so it could be anything). But we don't want
527 // to leave exit_code uninitialized, since that could cause
528 // random interpretations of the exit code. So we assume it
529 // terminated "normally" in this case.
530 *exit_code
= kNormalTerminationExitCode
;
532 // Assume the child has exited normally if we can't get the exit
534 return TERMINATION_STATUS_NORMAL_TERMINATION
;
536 if (tmp_exit_code
== STILL_ACTIVE
) {
537 DWORD wait_result
= WaitForSingleObject(handle
, 0);
538 if (wait_result
== WAIT_TIMEOUT
) {
540 *exit_code
= wait_result
;
541 return TERMINATION_STATUS_STILL_RUNNING
;
544 if (wait_result
== WAIT_FAILED
) {
545 DLOG_GETLASTERROR(ERROR
) << "WaitForSingleObject() failed";
547 DCHECK_EQ(WAIT_OBJECT_0
, wait_result
);
549 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
553 return TERMINATION_STATUS_ABNORMAL_TERMINATION
;
557 *exit_code
= tmp_exit_code
;
559 switch (tmp_exit_code
) {
560 case kNormalTerminationExitCode
:
561 return TERMINATION_STATUS_NORMAL_TERMINATION
;
562 case kDebuggerInactiveExitCode
: // STATUS_DEBUGGER_INACTIVE.
563 case kKeyboardInterruptExitCode
: // Control-C/end session.
564 case kDebuggerTerminatedExitCode
: // Debugger terminated process.
565 case kProcessKilledExitCode
: // Task manager kill.
566 return TERMINATION_STATUS_PROCESS_WAS_KILLED
;
568 // All other exit codes indicate crashes.
569 return TERMINATION_STATUS_PROCESS_CRASHED
;
573 bool WaitForExitCode(ProcessHandle handle
, int* exit_code
) {
574 bool success
= WaitForExitCodeWithTimeout(
575 handle
, exit_code
, base::TimeDelta::FromMilliseconds(INFINITE
));
576 CloseProcessHandle(handle
);
580 bool WaitForExitCodeWithTimeout(ProcessHandle handle
, int* exit_code
,
581 base::TimeDelta timeout
) {
582 if (::WaitForSingleObject(handle
, timeout
.InMilliseconds()) != WAIT_OBJECT_0
)
584 DWORD temp_code
; // Don't clobber out-parameters in case of failure.
585 if (!::GetExitCodeProcess(handle
, &temp_code
))
588 *exit_code
= temp_code
;
592 bool WaitForProcessesToExit(const FilePath::StringType
& executable_name
,
593 base::TimeDelta wait
,
594 const ProcessFilter
* filter
) {
595 const ProcessEntry
* entry
;
597 DWORD start_time
= GetTickCount();
599 NamedProcessIterator
iter(executable_name
, filter
);
600 while ((entry
= iter
.NextProcessEntry())) {
601 DWORD remaining_wait
= std::max
<int64
>(
602 0, wait
.InMilliseconds() - (GetTickCount() - start_time
));
603 HANDLE process
= OpenProcess(SYNCHRONIZE
,
605 entry
->th32ProcessID
);
606 DWORD wait_result
= WaitForSingleObject(process
, remaining_wait
);
607 CloseHandle(process
);
608 result
= result
&& (wait_result
== WAIT_OBJECT_0
);
614 bool WaitForSingleProcess(ProcessHandle handle
, base::TimeDelta wait
) {
616 if (!WaitForExitCodeWithTimeout(handle
, &exit_code
, wait
))
618 return exit_code
== 0;
621 bool CleanupProcesses(const FilePath::StringType
& executable_name
,
622 base::TimeDelta wait
,
624 const ProcessFilter
* filter
) {
625 bool exited_cleanly
= WaitForProcessesToExit(executable_name
, wait
, filter
);
627 KillProcesses(executable_name
, exit_code
, filter
);
628 return exited_cleanly
;
631 void EnsureProcessTerminated(ProcessHandle process
) {
632 DCHECK(process
!= GetCurrentProcess());
634 // If already signaled, then we are done!
635 if (WaitForSingleObject(process
, 0) == WAIT_OBJECT_0
) {
636 CloseHandle(process
);
640 MessageLoop::current()->PostDelayedTask(
642 base::Bind(&TimerExpiredTask::TimedOut
,
643 base::Owned(new TimerExpiredTask(process
))),
644 base::TimeDelta::FromMilliseconds(kWaitInterval
));
647 bool EnableLowFragmentationHeap() {
648 HMODULE kernel32
= GetModuleHandle(L
"kernel32.dll");
649 HeapSetFn heap_set
= reinterpret_cast<HeapSetFn
>(GetProcAddress(
651 "HeapSetInformation"));
653 // On Windows 2000, the function is not exported. This is not a reason to
658 unsigned number_heaps
= GetProcessHeaps(0, NULL
);
662 // Gives us some extra space in the array in case a thread is creating heaps
663 // at the same time we're querying them.
664 static const int MARGIN
= 8;
665 scoped_ptr
<HANDLE
[]> heaps(new HANDLE
[number_heaps
+ MARGIN
]);
666 number_heaps
= GetProcessHeaps(number_heaps
+ MARGIN
, heaps
.get());
670 for (unsigned i
= 0; i
< number_heaps
; ++i
) {
672 // Don't bother with the result code. It may fails on heaps that have the
673 // HEAP_NO_SERIALIZE flag. This is expected and not a problem at all.
675 HeapCompatibilityInformation
,
682 void EnableTerminationOnHeapCorruption() {
683 // Ignore the result code. Supported on XP SP3 and Vista.
684 HeapSetInformation(NULL
, HeapEnableTerminationOnCorruption
, NULL
, 0);
687 void EnableTerminationOnOutOfMemory() {
688 std::set_new_handler(&OnNoMemory
);
691 void RaiseProcessToHighPriority() {
692 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
);