Files
nt-lite/code/user/tests/process_protection_smoke/process_protection_smoke.c
T

104 lines
3.1 KiB
C

// Protected-process smoke test.
// Verifies that kernel-owned processes remain queryable but cannot be terminated.
#include <stddef.h>
#include <stdint.h>
#include <ntlite/syscall.h>
#define MAX_PROCESSES 16u
// Prints one NUL-terminated string to the console.
static void print(const char* text) {
SYS_WRITE_CONSOLE_REQUEST request = { SysSvFromCstr(text) };
(void)SysWriteConsole(&request);
}
// Prints one unsigned integer to the console.
static void print_u32(uint32_t value) {
char buffer[16];
size_t length = 0;
if (value == 0) {
print("0");
return;
}
while (value && length < sizeof(buffer)) {
buffer[length++] = (char)('0' + (value % 10u));
value /= 10u;
}
while (length) {
char digit = buffer[--length];
SYS_WRITE_CONSOLE_REQUEST request = { SysSvFromParts(&digit, 1) };
(void)SysWriteConsole(&request);
}
}
// Terminates the current test process.
static void exit_now(int32_t code) {
for (;;) (void)SysExitProcess(code);
}
// Fails the test with one status value.
static void fail_status(const char* operation, uint32_t status) {
print("process_protection_smoke: ");
print(operation);
print(" status=");
print_u32(status);
print("\n");
exit_now(1);
}
// Verifies one protected process remains alive after a kill attempt.
static void verify_protected_process(const SYS_PROCESS_INFO* process) {
uint32_t handle = 0;
uint32_t status = SysOpenProcess(process->ProcessId, &handle);
if (status != NTLSTATUS_SUCCESS)
fail_status("open protected process", status);
status = SysKillProcess(handle, (int32_t)NTLSTATUS_PROCESS_KILLED);
if (status != NTLSTATUS_ACCESS_DENIED) {
SysCloseHandle(handle);
fail_status("kill protected process", status);
}
status = SysWaitSingle(handle, SYS_WAIT_FLAG_NONE, 0);
SysCloseHandle(handle);
if (status != NTLSTATUS_TIMEOUT)
fail_status("protected process remained signaled", status);
}
// Runs the protected-process contract checks.
void main(void) {
print("process_protection_smoke: start\n");
SYS_PROCESS_INFO processes[MAX_PROCESSES];
size_t count = 0;
uint32_t status = SysGetProcessList(processes, MAX_PROCESSES, &count);
if (status != NTLSTATUS_SUCCESS)
fail_status("query process list", status);
int sawIdle = 0;
int sawSystem = 0;
size_t limit = count < MAX_PROCESSES ? count : MAX_PROCESSES;
for (size_t i = 0; i < limit; i++) {
const SYS_PROCESS_INFO* process = &processes[i];
if (!(process->Flags & (SYS_PROCESS_FLAG_IDLE | SYS_PROCESS_FLAG_SYSTEM)))
continue;
if (!(process->Flags & SYS_PROCESS_FLAG_TERMINATION_PROTECTED))
fail_status("missing protected flag", process->ProcessId);
verify_protected_process(process);
if (process->Flags & SYS_PROCESS_FLAG_IDLE) sawIdle = 1;
if (process->Flags & SYS_PROCESS_FLAG_SYSTEM) sawSystem = 1;
}
if (!sawIdle || !sawSystem)
fail_status("missing kernel process", (uint32_t)((sawIdle ? 1u : 0u) | (sawSystem ? 2u : 0u)));
print("process_protection_smoke: PASS\n");
exit_now(0);
}