blob: 2b6b9307e677868ca81166f350b4924dd24e85ae [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
[email protected]307af212013-07-10 18:36:092// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/process/kill.h"
6
[email protected]307af212013-07-10 18:36:097#include <windows.h>
Bruce Dawsona1e1cfcb2022-11-22 20:04:358
avibeced7c2015-12-24 06:47:599#include <io.h>
10#include <stdint.h>
[email protected]307af212013-07-10 18:36:0911
Takuto Ikutac8d6b16f2024-04-15 16:59:1912#include <algorithm>
13
[email protected]307af212013-07-10 18:36:0914#include "base/logging.h"
Hans Wennborgafeb3902020-06-17 14:42:2915#include "base/notreached.h"
wfhfa40c2722016-07-26 01:12:2816#include "base/process/memory.h"
[email protected]307af212013-07-10 18:36:0917#include "base/process/process_iterator.h"
[email protected]307af212013-07-10 18:36:0918
19namespace base {
20
[email protected]307af212013-07-10 18:36:0921TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
Wez05c2c682017-08-17 16:20:1122 DCHECK(exit_code);
23
[email protected]307af212013-07-10 18:36:0924 DWORD tmp_exit_code = 0;
25
26 if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
[email protected]ad8cfa92014-05-21 20:06:2327 DPLOG(FATAL) << "GetExitCodeProcess() failed";
Wez05c2c682017-08-17 16:20:1128
29 // This really is a random number. We haven't received any
30 // information about the exit code, presumably because this
31 // process doesn't have permission to get the exit code, or
32 // because of some other cause for GetExitCodeProcess to fail
33 // (MSDN docs don't give the possible failure error codes for
34 // this function, so it could be anything). But we don't want
35 // to leave exit_code uninitialized, since that could cause
36 // random interpretations of the exit code. So we assume it
37 // terminated "normally" in this case.
Bruce Dawsonec0158512017-11-16 09:10:4038 *exit_code = win::kNormalTerminationExitCode;
Wez05c2c682017-08-17 16:20:1139
[email protected]307af212013-07-10 18:36:0940 // Assume the child has exited normally if we can't get the exit
41 // code.
42 return TERMINATION_STATUS_NORMAL_TERMINATION;
43 }
44 if (tmp_exit_code == STILL_ACTIVE) {
45 DWORD wait_result = WaitForSingleObject(handle, 0);
46 if (wait_result == WAIT_TIMEOUT) {
Peter Kasting4d3664b2022-06-16 19:27:5447 *exit_code = static_cast<int>(wait_result);
[email protected]307af212013-07-10 18:36:0948 return TERMINATION_STATUS_STILL_RUNNING;
49 }
50
51 if (wait_result == WAIT_FAILED) {
[email protected]ad8cfa92014-05-21 20:06:2352 DPLOG(ERROR) << "WaitForSingleObject() failed";
Sorin Jianu08f96122024-03-23 00:42:4453 *exit_code = static_cast<int>(wait_result);
[email protected]307af212013-07-10 18:36:0954 } else {
55 DCHECK_EQ(WAIT_OBJECT_0, wait_result);
Sorin Jianu08f96122024-03-23 00:42:4456 DLOG(ERROR) << "The process used 0x103 (STILL_ACTIVE) as exit code.";
57 *exit_code = static_cast<int>(tmp_exit_code);
[email protected]307af212013-07-10 18:36:0958 }
59
60 return TERMINATION_STATUS_ABNORMAL_TERMINATION;
61 }
62
Peter Kasting4d3664b2022-06-16 19:27:5463 *exit_code = static_cast<int>(tmp_exit_code);
[email protected]307af212013-07-10 18:36:0964
Will Harris07925d12019-10-31 03:03:0565 // clang-format off
[email protected]307af212013-07-10 18:36:0966 switch (tmp_exit_code) {
Bruce Dawsonec0158512017-11-16 09:10:4067 case win::kNormalTerminationExitCode:
[email protected]307af212013-07-10 18:36:0968 return TERMINATION_STATUS_NORMAL_TERMINATION;
Bruce Dawsonec0158512017-11-16 09:10:4069 case win::kDebuggerInactiveExitCode: // STATUS_DEBUGGER_INACTIVE.
70 case win::kKeyboardInterruptExitCode: // Control-C/end session.
71 case win::kDebuggerTerminatedExitCode: // Debugger terminated process.
72 case win::kProcessKilledExitCode: // Task manager kill.
[email protected]307af212013-07-10 18:36:0973 return TERMINATION_STATUS_PROCESS_WAS_KILLED;
Bruce Dawsonec0158512017-11-16 09:10:4074 case win::kSandboxFatalMemoryExceeded: // Terminated process due to
75 // exceeding the sandbox job
76 // object memory limits.
77 case win::kOomExceptionCode: // Ran out of memory.
wfhfa40c2722016-07-26 01:12:2878 return TERMINATION_STATUS_OOM;
Will Harris07925d12019-10-31 03:03:0579 // This exit code means the process failed an OS integrity check.
80 // This is tested in ProcessMitigationsTest.* in sandbox.
81 case win::kStatusInvalidImageHashExitCode:
82 return TERMINATION_STATUS_INTEGRITY_FAILURE;
[email protected]307af212013-07-10 18:36:0983 default:
84 // All other exit codes indicate crashes.
85 return TERMINATION_STATUS_PROCESS_CRASHED;
86 }
Will Harris07925d12019-10-31 03:03:0587 // clang-format on
[email protected]307af212013-07-10 18:36:0988}
89
[email protected]307af212013-07-10 18:36:0990bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
rvargas2f70a152015-02-24 00:28:1191 TimeDelta wait,
[email protected]307af212013-07-10 18:36:0992 const ProcessFilter* filter) {
[email protected]307af212013-07-10 18:36:0993 bool result = true;
94 DWORD start_time = GetTickCount();
95
96 NamedProcessIterator iter(executable_name, filter);
[email protected]ed8e57da2014-07-03 07:03:3997 for (const ProcessEntry* entry = iter.NextProcessEntry(); entry;
98 entry = iter.NextProcessEntry()) {
avibeced7c2015-12-24 06:47:5999 DWORD remaining_wait = static_cast<DWORD>(
100 std::max(static_cast<int64_t>(0),
101 wait.InMilliseconds() - (GetTickCount() - start_time)));
Peter Kasting134ef9af2024-12-28 02:30:09102 HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, entry->th32ProcessID);
brucedawsond3509432015-09-18 18:28:13103 DWORD wait_result = WaitForSingleObject(process, remaining_wait);
104 CloseHandle(process);
[email protected]ed8e57da2014-07-03 07:03:39105 result &= (wait_result == WAIT_OBJECT_0);
[email protected]307af212013-07-10 18:36:09106 }
107
108 return result;
109}
110
[email protected]307af212013-07-10 18:36:09111bool CleanupProcesses(const FilePath::StringType& executable_name,
rvargas2f70a152015-02-24 00:28:11112 TimeDelta wait,
[email protected]307af212013-07-10 18:36:09113 int exit_code,
114 const ProcessFilter* filter) {
Peter Kasting134ef9af2024-12-28 02:30:09115 if (WaitForProcessesToExit(executable_name, wait, filter)) {
[email protected]ed8e57da2014-07-03 07:03:39116 return true;
Peter Kasting134ef9af2024-12-28 02:30:09117 }
[email protected]ed8e57da2014-07-03 07:03:39118 KillProcesses(executable_name, exit_code, filter);
119 return false;
[email protected]307af212013-07-10 18:36:09120}
121
[email protected]307af212013-07-10 18:36:09122} // namespace base