redo boot around an explicit system volume and fixed kernel/HAL images, redo volumes and filesystem paths around capabilities instead of drive numbers and kernel CWD state, add a capability/security model with derived and revocable handles and security contexts, add port IPC and rssrv to manage the userspace resource namespace and publish the system volume, move process, dll and path loading to userspace and add process builder syscalls, init now supervises rssrv and the session process, redo the syscall ABI around request structs and four arguments, add a volume manager and proper partition arrival/removal handling so FAT and NTFS mount dynamically, clean up the HAL/DDK boundary so drivers don't depend on HAL internals, save fpu state properly now, the serial driver doesn't hang on a missing port, fix AHCI startup races, fix timeout accounting, fix shared mmap writeback, more smoke tests
This commit is contained in:
1 parent
4add6789ba
commit
f882d339fb
232 files changed
+20934
-8898
No files matched your search
@@ -1,155 +1,127 @@
|
||||
// User-mode smoke test for public dynamic module loading.
|
||||
// User-mode smoke test for process-local userspace module loading.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include <ntlite/module_loader.h>
|
||||
#include <ntlite/resource.h>
|
||||
|
||||
// Prints one NUL-terminated string to the kernel console.
|
||||
static void print(const char* s) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
// Prints one unsigned integer.
|
||||
static void print_u64(uint64_t v) {
|
||||
char buf[32];
|
||||
int i = 0;
|
||||
if (v == 0) {
|
||||
print("0");
|
||||
return;
|
||||
}
|
||||
while (v && i < (int)sizeof(buf)) {
|
||||
buf[i++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
if (v == 0) { print("0"); return; }
|
||||
while (v && i < (int)sizeof(buf)) { buf[i++] = (char)('0' + (v % 10)); v /= 10; }
|
||||
while (i--) {
|
||||
char c = buf[i];
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { sizeof(req), SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current process.
|
||||
static void exit_now(int32_t code) {
|
||||
while (true) SysExitProcess(code);
|
||||
}
|
||||
|
||||
// Fails the test with one message.
|
||||
static void fail(const char* message) {
|
||||
print("module_load_smoke: ");
|
||||
print(message);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void exit_now(int32_t code) { while (true) SysExitProcess(code); }
|
||||
static void fail(const char* message) { print("module_load_smoke: "); print(message); print("\n"); exit_now(1); }
|
||||
static void fail_status(const char* what, uint32_t status) {
|
||||
print("module_load_smoke: ");
|
||||
print(what);
|
||||
print(" status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
print("module_load_smoke: "); print(what); print(" status="); print_u64(status); print("\n"); exit_now(1);
|
||||
}
|
||||
|
||||
// Checks whether one public module snapshot has the expected shape.
|
||||
static void check_module_info(const SYS_MODULE_INFO* info) {
|
||||
if (!info) fail("null module info");
|
||||
if (info->Size != sizeof(*info)) fail("module info size mismatch");
|
||||
if (info->Version != SYS_MODULE_INFO_VERSION) fail("module info version mismatch");
|
||||
if (info->Base == 0 || info->ImageSize == 0) fail("module has empty mapping");
|
||||
if ((info->Flags & SYS_MODULE_FLAG_PUBLIC_REF) == 0) fail("module missing public reference flag");
|
||||
if (info->PublicRefCount == 0 || info->TotalRefCount == 0) fail("module reference counts missing");
|
||||
static void check_module_info(const NTL_MODULE_INFO* info) {
|
||||
if (!info || !info->Base || !info->Size) fail("module has empty mapping");
|
||||
if (info->PublicRefCount == 0) fail("module public reference missing");
|
||||
if (strcmp(info->Name, "posix.dll") != 0) fail("module name mismatch");
|
||||
}
|
||||
|
||||
// Returns whether the current module list contains the specified base address.
|
||||
static int module_list_contains(uintptr_t base) {
|
||||
size_t count = 0;
|
||||
uint32_t status = SysGetModuleList(0, 0, &count);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("query module count", status);
|
||||
uint32_t status = NtlGetModuleList(0, 0, &count);
|
||||
if (status != NTLSTATUS_BUFFER_TOO_SMALL && status != NTLSTATUS_SUCCESS)
|
||||
fail_status("query module count", status);
|
||||
if (count == 0) return 0;
|
||||
if (count > 32) fail("module count unexpectedly large");
|
||||
|
||||
SYS_MODULE_INFO modules[32];
|
||||
memset(modules, 0, sizeof(modules));
|
||||
status = SysGetModuleList(modules, count, &count);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("query module list", status);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (modules[i].Base == base)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (count > SIZE_MAX / sizeof(NTL_MODULE_INFO)) fail("module count overflow");
|
||||
size_t bytes = count * sizeof(NTL_MODULE_INFO);
|
||||
size_t pages = (bytes + 4095u) / 4096u;
|
||||
void* memory = 0;
|
||||
SYS_ALLOC_VM_REQUEST alloc;
|
||||
memset(&alloc, 0, sizeof(alloc));
|
||||
alloc.Size = sizeof(alloc);
|
||||
alloc.Protect = SYS_VM_READWRITE;
|
||||
alloc.Flags = SYS_VM_FLAG_NONE;
|
||||
alloc.PageCount = pages;
|
||||
alloc.BaseOut = &memory;
|
||||
status = SysAllocVm(&alloc);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("allocate module list", status);
|
||||
NTL_MODULE_INFO* modules = (NTL_MODULE_INFO*)memory;
|
||||
memset(modules, 0, bytes);
|
||||
size_t copied = count;
|
||||
status = NtlGetModuleList(modules, count, &copied);
|
||||
if (status != NTLSTATUS_SUCCESS) { (void)SysFreeVm(memory); fail_status("query module list", status); }
|
||||
int found = 0;
|
||||
for (size_t i = 0; i < copied; ++i) if (modules[i].Base == base) { found = 1; break; }
|
||||
(void)SysFreeVm(memory);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
// Verifies export lookup through a module handle.
|
||||
static void check_export_lookup(void) {
|
||||
uint32_t handle = 0;
|
||||
SYS_LOAD_MODULE_REQUEST req;
|
||||
// Loads one module through the userspace registry with the specified filename policy.
|
||||
static NTL_MODULE_HANDLE load_module(SYS_HANDLE root, const char* path,
|
||||
NTL_MODULE_NAME_RESOLVER resolver, NTL_MODULE_INFO* info) {
|
||||
NTL_MODULE_HANDLE handle = NTL_MODULE_HANDLE_INVALID;
|
||||
NTL_LOAD_MODULE_AT_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Path = SysSvFromCstr("syscall.dll");
|
||||
req.Flags = NTL_MODULE_LOAD_FLAG_NONE;
|
||||
req.RootHandle = root;
|
||||
req.Path = SysSvFromCstr(path);
|
||||
req.ModuleRootHandle = root;
|
||||
req.ModuleDirectory = SYS_SV_LITERAL("system");
|
||||
req.ResolveModuleName = resolver;
|
||||
req.ModuleHandleOut = &handle;
|
||||
|
||||
uint32_t status = SysLoadModule(&req);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("load syscall.dll", status);
|
||||
if (handle == 0) fail("syscall load returned null handle");
|
||||
|
||||
uintptr_t address = 0;
|
||||
SYS_GET_MODULE_EXPORT_REQUEST exportReq;
|
||||
memset(&exportReq, 0, sizeof(exportReq));
|
||||
exportReq.Size = sizeof(exportReq);
|
||||
exportReq.ModuleHandle = handle;
|
||||
exportReq.Name = SysSvFromCstr("SysGetCurrentPid");
|
||||
exportReq.AddressOut = &address;
|
||||
|
||||
status = SysGetModuleExport(&exportReq);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("lookup SysGetCurrentPid", status);
|
||||
if (address == 0) fail("export address is zero");
|
||||
|
||||
status = SysUnloadModule(handle);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("unload syscall.dll handle", status);
|
||||
req.InfoOut = info;
|
||||
uint32_t status = NtlLoadModuleAt(&req);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("load module", status);
|
||||
if (handle == NTL_MODULE_HANDLE_INVALID) fail("load returned null handle");
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Runs the public dynamic module loader smoke test.
|
||||
// Runs the userspace process-module loader smoke test.
|
||||
int main(void) {
|
||||
print("module_load_smoke: start\n");
|
||||
check_export_lookup();
|
||||
SYS_HANDLE root = SYS_HANDLE_INVALID;
|
||||
uint32_t status = NtlResourceOpenSystemRoot(SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &root);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("open system root", status);
|
||||
|
||||
uint32_t handle = 0;
|
||||
SYS_MODULE_INFO info;
|
||||
NTL_MODULE_HANDLE syscallModule = load_module(root, "system/syscall.dll",
|
||||
NtlResolveModuleNameIdentity, 0);
|
||||
uintptr_t address = 0;
|
||||
status = NtlGetModuleExport(syscallModule, SysSvFromCstr("SysGetCurrentPid"), &address);
|
||||
if (status != NTLSTATUS_SUCCESS || !address) fail_status("lookup SysGetCurrentPid", status);
|
||||
status = NtlUnloadModule(syscallModule);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("unload syscall.dll", status);
|
||||
|
||||
NTL_MODULE_INFO info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
SYS_LOAD_MODULE_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Path = SysSvFromCstr("posix.dll");
|
||||
req.ModuleHandleOut = &handle;
|
||||
req.InfoOut = &info;
|
||||
|
||||
uint32_t status = SysLoadModule(&req);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("load posix.dll", status);
|
||||
if (handle == 0) fail("load returned null handle");
|
||||
NTL_MODULE_HANDLE posix = load_module(root, "system/msvcrt.dll",
|
||||
NtlResolveSystemModuleName, &info);
|
||||
check_module_info(&info);
|
||||
if (!module_list_contains(info.Base)) fail("loaded module absent from list");
|
||||
|
||||
SYS_MODULE_INFO byHandle;
|
||||
NTL_MODULE_INFO byHandle;
|
||||
memset(&byHandle, 0, sizeof(byHandle));
|
||||
status = SysGetModuleInfo(handle, &byHandle);
|
||||
status = NtlGetModuleInfo(posix, &byHandle);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("get module info", status);
|
||||
check_module_info(&byHandle);
|
||||
if (byHandle.Base != info.Base) fail("module handle base mismatch");
|
||||
|
||||
status = SysUnloadModule(handle);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("unload module", status);
|
||||
|
||||
memset(&byHandle, 0, sizeof(byHandle));
|
||||
status = SysGetModuleInfo(handle, &byHandle);
|
||||
status = NtlUnloadModule(posix);
|
||||
if (status != NTLSTATUS_SUCCESS) fail_status("unload posix.dll", status);
|
||||
status = NtlGetModuleInfo(posix, &byHandle);
|
||||
if (status != NTLSTATUS_INVALID_HANDLE) fail_status("query unloaded handle", status);
|
||||
|
||||
(void)SysCloseHandle(root);
|
||||
print("module_load_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user