...
Processes behave similar to threads, and so share the same concerns. Do not use the TerminateThread()
or TerminateProcess()
APIs. Instead, you should prefer to exit threads and processes by returning from the entrypoint, by calling ExitThread()
, or by calling ExitProcess()
.
Noncompliant Code Example
In the following example, TerminateThread()
is used to forcibly terminate another thread, which can leak resources and leave the application in an indeterminate state.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <Windows.h> DWORD ThreadID; /* Filled in by call to CreateThread */ /* Thread 1 */ DWORD WINAPI ThreadProc(LPVOID param) { /* Performing work */ } /* Thread 2 */ HANDLE hThread = OpenThread(THREAD_TERMINATE, FALSE, ThreadID); if (hThread) { TerminateThread(hThread, 0xFF); CloseHandle(hThread); } |
Compliant Solution
The compliant solution avoids calling TerminateThread()
by requesting the thread terminate itself by exiting its entrypoint. It does so in a lock-free, thread-safe manner by using the InterlockedCompareExchange()
and InterlockedExchange()
Win32 APIs.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <Windows.h> DWORD ThreadID; /* Filled in by call to CreateThread */ LONG ShouldThreadExit = 0; /* Thread 1 */ DWORD WINAPI ThreadProc(LPVOID param) { while (1) { /* Performing work */ if (1 == InterlockedCompareExchange(&ShouldThreadExit, 0, 1)) return 0xFF; } } /* Thread 2 */ InterlockedExchange(&ShouldThreadExit, 1); |
Risk Assessment
Incorrectly using threads that asynchronously cancel may result in silent corruption, resource leaks, and, in the worst case, unpredictable interactions.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
WIN31-C | High | Likely | High | P9 | L2 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
TODO (notably, should be one about using ExitThread()
from C++ code.
Bibliography
...