Files
nt-lite/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c
T
maksw 73abd6f90d isolate POSIX builds from the host UCRT, wire lwext4 and ntfs-3g as ext4.sys and ntfs.sys, split the FAT driver into directory/file/async/driver/mount units, add posixsrv and dwm plus input/console/desktop syscall clients and a pile of new smoke targets, rename serial.sys to cereal.sys, name HDA/USB/lwIP/AHCI workers, harden ATA probing/reset/removal around actual hardware deadlines, absent-channel detection, diagnostics and explicit worker lifetime, redo ACPI S5 shutdown around GAS/MMIO and HW-reduced firmware, scan SSDTs for _S5 and deal with Intel SMI sleep trapping, make serial and SMP timeouts use real monotonic deadlines, add thread names and fix terminal thread teardown, scheduler and APC prepare/commit races, make advisory file locks queryable and preserve split ranges and add mutable file append state, add shared-memory pipes with kernel-assisted wait/wake, introduce capability-scoped input and display managers, split surface map rights into read/write, add explicit unmap and replace present with commit/generation/damage tracking while keeping physical presentation under the display manager, decouple native exception classes from Win32 exception numbers and translate them in kernel32, add opaque process startup data, bump the resource protocol to v3 with namespace directories, symlinks and enumeration and service control to v2 with generic READY handle exports, add the new POSIX errno/status surface and rebuild fds around posixsrv-owned shared open descriptions, descriptor-local flags, exact inheritance snapshots, dup/fcntl/record locks and shared-ring pipes, add waitpid, POSIX credentials/groups/sessions/passwd/group lookups and move sockets onto stable open descriptions, port the shells and apps to the new console/input services and surface commit API, teach init to load services.ini and start/supervise RSSRV, DWM and generic services under restricted capabilities while publishing their endpoints through RSSRV, split RSSRV into namespace, volume, display, session, input, console and resource components and make /SystemRoot a real symlink to the independently published system volume, shift the syscall table again, expand lock/resource/surface/POSIX/service/thread smoke coverage, make docs scream ASK QUESTIONS and DISCUSS at LLMs, replace MIT No Attribution with WTFPL+.
2026-09-16 10:33:20 +02:00

166 lines
5.5 KiB
C

// User-mode smoke test for POSIX process/thread runtime state and public headers.
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <dlfcn.h>
#include <pwd.h>
#include <grp.h>
#include <ntlite/syscall.h>
static volatile int gWorkerErrno;
static volatile uintptr_t gWorkerErrnoAddress;
static volatile int gWorkerDlErrorOk;
static volatile pid_t gWorkerPid;
// Writes one NUL-terminated string to stdout.
static void print(const char* text) {
(void)write(1, text, strlen(text));
}
// Terminates the smoke test with one diagnostic.
static void fail(const char* message) {
print("posix_runtime_smoke: ");
print(message);
print("\n");
exit(1);
}
// Mutates errno and dlerror in a second POSIX thread.
static void* worker(void* argument) {
(void)argument;
if (errno != 0)
return (void*)1;
gWorkerErrnoAddress = (uintptr_t)__ntl_posix_errno_location();
gWorkerPid = getpid();
errno = 222;
if (dlsym((void*)0, "worker_missing_symbol") != (void*)0)
return (void*)2;
char* error = dlerror();
if (!error || !error[0] || dlerror() != (char*)0)
return (void*)3;
gWorkerErrno = errno;
gWorkerDlErrorOk = 1;
return (void*)0x1234;
}
// Runs the POSIX runtime foundation smoke test.
int main(void) {
print("posix_runtime_smoke: start\n");
if (_POSIX_VERSION != 199009L)
fail("wrong POSIX profile version");
uintptr_t mainErrnoAddress = (uintptr_t)__ntl_posix_errno_location();
if (!mainErrnoAddress)
fail("main errno address is null");
pid_t stablePid = getpid();
if (stablePid <= 0)
fail("stable POSIX pid was invalid");
if ((uint32_t)stablePid == SysGetCurrentPid())
fail("getpid leaked native pid");
errno = 77;
if (dlsym((void*)0, "main_missing_symbol") != (void*)0)
fail("main dlsym unexpectedly succeeded");
if (!dlerror())
fail("main dlerror was not set");
// Re-arm one main-thread loader error so the worker can prove isolation.
if (dlsym((void*)0, "main_missing_symbol_2") != (void*)0)
fail("second main dlsym unexpectedly succeeded");
errno = 77;
pthread_t thread;
int createStatus = pthread_create(&thread, (const pthread_attr_t*)0, worker, (void*)0);
if (createStatus != 0)
fail("pthread_create failed");
void* result = (void*)0;
int joinStatus = pthread_join(thread, &result);
if (joinStatus != 0)
fail("pthread_join failed");
if (result != (void*)0x1234)
fail("worker returned wrong value");
if (gWorkerErrnoAddress == 0 || gWorkerErrnoAddress == mainErrnoAddress)
fail("errno storage was shared between threads");
if (gWorkerPid != stablePid)
fail("worker did not inherit logical POSIX process identity");
if (gWorkerErrno != EINVAL || !gWorkerDlErrorOk)
fail("worker thread-local state was wrong");
if (errno != 77)
fail("worker changed main errno");
char* mainError = dlerror();
if (!mainError || !mainError[0])
fail("worker consumed main dlerror");
if (dlerror() != (char*)0)
fail("main dlerror did not clear");
if (getuid() != 0 || geteuid() != 0 || getgid() != 0 || getegid() != 0)
fail("initial synthetic credentials were wrong");
if (getgroups(0, (gid_t*)0) != 0)
fail("initial supplementary group set was wrong");
char* login = getlogin();
if (!login || strcmp(login, "root") != 0)
fail("initial login identity was wrong");
struct passwd* root = getpwnam("root");
if (!root || root->pw_uid != 0 || root->pw_gid != 0 || strcmp(root->pw_name, "root") != 0)
fail("root passwd lookup failed");
struct passwd* user = getpwuid(1000);
if (!user || user->pw_uid != 1000 || user->pw_gid != 1000 || strcmp(user->pw_name, "user") != 0)
fail("user passwd lookup failed");
struct group* users = getgrnam("users");
if (!users || users->gr_gid != 1000 || strcmp(users->gr_name, "users") != 0 ||
!users->gr_mem || users->gr_mem[0] != (char*)0)
fail("group lookup failed");
if (getgrgid(0) == (struct group*)0)
fail("group id lookup failed");
if (getpgrp() != stablePid)
fail("initial process group was wrong");
errno = 0;
if (setsid() != (pid_t)-1 || errno != EPERM)
fail("session leader unexpectedly created another session");
errno = 0;
if (setpgid(0, 0) != -1 || errno != EPERM)
fail("session leader unexpectedly changed process group");
char originalCwd[256];
if (!getcwd(originalCwd, sizeof(originalCwd)))
fail("getcwd before chdir failed");
if (chdir("/") != 0)
fail("chdir root failed");
char rootCwd[16];
if (!getcwd(rootCwd, sizeof(rootCwd)) || strcmp(rootCwd, "/") != 0)
fail("chdir root did not update cwd");
if (chdir(originalCwd) != 0)
fail("cwd restore failed");
if (setgid(1000) != 0 || getgid() != 1000 || getegid() != 1000)
fail("root setgid failed");
if (setuid(1000) != 0 || getuid() != 1000 || geteuid() != 1000)
fail("root setuid failed");
errno = 0;
if (setgid(0) != -1 || errno != EPERM)
fail("dropped uid retained setgid authority");
errno = 0;
if (setuid(0) != -1 || errno != EPERM)
fail("dropped uid regained root");
if (!getlogin() || strcmp(getlogin(), "root") != 0)
fail("login identity changed with effective uid");
print("posix_runtime_smoke: PASS\n");
return 0;
}