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
@@ -0,0 +1,200 @@
|
||||
// Resource-service smoke test. Proves public RSSRV lookup is capability-based and namespace administration is private.
|
||||
|
||||
#include <ntlite/resource.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include <ntlite/path.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static void print(const char* text) {
|
||||
SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) };
|
||||
(void)SysWriteConsole(&request);
|
||||
}
|
||||
|
||||
|
||||
// Builds one /Device/HarddiskVolumeN resource path.
|
||||
static SYS_STRING_VIEW make_volume_path(uint32_t index, char* buffer, size_t capacity) {
|
||||
static const char prefix[] = "/Device/HarddiskVolume";
|
||||
size_t prefixLength = sizeof(prefix) - 1u;
|
||||
if (!index || !buffer || capacity <= prefixLength)
|
||||
return SysSvFromParts((const char*)0, 0);
|
||||
|
||||
char digits[10];
|
||||
size_t digitCount = 0;
|
||||
do {
|
||||
digits[digitCount++] = (char)('0' + (index % 10u));
|
||||
index /= 10u;
|
||||
} while (index && digitCount < sizeof(digits));
|
||||
if (prefixLength + digitCount + 1u > capacity)
|
||||
return SysSvFromParts((const char*)0, 0);
|
||||
|
||||
memcpy(buffer, prefix, prefixLength);
|
||||
for (size_t i = 0; i < digitCount; ++i)
|
||||
buffer[prefixLength + i] = digits[digitCount - 1u - i];
|
||||
buffer[prefixLength + digitCount] = '\0';
|
||||
return SysSvFromParts(buffer, prefixLength + digitCount);
|
||||
}
|
||||
|
||||
static int fail(const char* what, KSTATUS status) {
|
||||
(void)status;
|
||||
print("resource_service_smoke: FAIL ");
|
||||
print(what);
|
||||
print("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
SYS_HANDLE session = SYS_HANDLE_INVALID;
|
||||
KSTATUS status = NtlResourceConnect(&session);
|
||||
if (!KSUCCESS(status)) return fail("connect", status);
|
||||
|
||||
uint32_t kind = NTL_RESOURCE_KIND_INVALID;
|
||||
status = NtlResourceQuery(session, SYS_SV_LITERAL("/SystemRoot"), &kind);
|
||||
if (!KSUCCESS(status) || kind != NTL_RESOURCE_KIND_VOLUME)
|
||||
return fail("query /SystemRoot", status);
|
||||
|
||||
// RSSRV assigns its own monotonic /Device/HarddiskVolumeN names to mounted IO_VOLUME instances.
|
||||
uint32_t publishedVolumes = 0;
|
||||
uint32_t systemVolumePublished = 0;
|
||||
for (uint32_t index = 1; index <= 32; ++index) {
|
||||
char volumePathBuffer[48];
|
||||
SYS_STRING_VIEW volumePath = make_volume_path(index, volumePathBuffer, sizeof(volumePathBuffer));
|
||||
if (!volumePath.Data)
|
||||
return fail("build dynamic volume path", NTLSTATUS_FAILURE);
|
||||
|
||||
SYS_HANDLE published = SYS_HANDLE_INVALID;
|
||||
status = NtlResourceLookup(session, volumePath, SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &published);
|
||||
if (status == NTLSTATUS_NOT_FOUND)
|
||||
continue;
|
||||
if (!KSUCCESS(status))
|
||||
return fail("lookup dynamic volume", status);
|
||||
publishedVolumes++;
|
||||
|
||||
SYS_HANDLE probe = SYS_HANDLE_INVALID;
|
||||
SYS_OPEN_FILE_AT_REQUEST probeOpen;
|
||||
memset(&probeOpen, 0, sizeof(probeOpen));
|
||||
probeOpen.Size = sizeof(probeOpen);
|
||||
probeOpen.RootHandle = published;
|
||||
probeOpen.Path = SYS_SV_LITERAL("system/init.exe");
|
||||
probeOpen.Access = SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY;
|
||||
probeOpen.Disposition = SYS_FILE_OPEN_EXISTING;
|
||||
probeOpen.Flags = SYS_FILE_FLAG_NONE;
|
||||
probeOpen.HandleOut = &probe;
|
||||
KSTATUS probeStatus = SysOpenFileAt(&probeOpen);
|
||||
if (KSUCCESS(probeStatus)) {
|
||||
systemVolumePublished = 1;
|
||||
(void)SysCloseHandle(probe);
|
||||
} else if (probeStatus != NTLSTATUS_NOT_FOUND) {
|
||||
(void)SysCloseHandle(published);
|
||||
return fail("probe dynamic volume", probeStatus);
|
||||
}
|
||||
(void)SysCloseHandle(published);
|
||||
}
|
||||
if (!publishedVolumes || !systemVolumePublished)
|
||||
return fail("dynamic volume publication", NTLSTATUS_NOT_FOUND);
|
||||
|
||||
SYS_HANDLE volume = SYS_HANDLE_INVALID;
|
||||
status = NtlResourceLookup(session, SYS_SV_LITERAL("/SystemRoot"),
|
||||
SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &volume);
|
||||
if (!KSUCCESS(status)) return fail("lookup /SystemRoot", status);
|
||||
|
||||
SYS_HANDLE file = SYS_HANDLE_INVALID;
|
||||
SYS_OPEN_FILE_AT_REQUEST open;
|
||||
memset(&open, 0, sizeof(open));
|
||||
open.Size = sizeof(open);
|
||||
open.RootHandle = volume;
|
||||
open.Path = SYS_SV_LITERAL("system/init.exe");
|
||||
open.Access = SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY;
|
||||
open.Disposition = SYS_FILE_OPEN_EXISTING;
|
||||
open.Flags = SYS_FILE_FLAG_NONE;
|
||||
open.HandleOut = &file;
|
||||
status = SysOpenFileAt(&open);
|
||||
if (!KSUCCESS(status)) return fail("open through resource volume", status);
|
||||
(void)SysCloseHandle(file);
|
||||
(void)SysCloseHandle(volume);
|
||||
|
||||
// RESOLVE returns the longest bound resource prefix and leaves only a relative tail for I/O.
|
||||
SYS_HANDLE resolvedRoot = SYS_HANDLE_INVALID;
|
||||
uint32_t resolvedLength = 0;
|
||||
status = NtlResourceResolve(session, SYS_SV_LITERAL("/SystemRoot/system/init.exe"),
|
||||
NTL_RESOURCE_FLAG_NONE, &resolvedRoot, &kind, &resolvedLength);
|
||||
if (!KSUCCESS(status) || kind != NTL_RESOURCE_KIND_VOLUME ||
|
||||
resolvedLength != sizeof("/SystemRoot") - 1u)
|
||||
return fail("resolve longest prefix", status);
|
||||
|
||||
file = SYS_HANDLE_INVALID;
|
||||
memset(&open, 0, sizeof(open));
|
||||
open.Size = sizeof(open);
|
||||
open.RootHandle = resolvedRoot;
|
||||
open.Path = SYS_SV_LITERAL("system/init.exe");
|
||||
open.Access = SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY;
|
||||
open.Disposition = SYS_FILE_OPEN_EXISTING;
|
||||
open.Flags = SYS_FILE_FLAG_NONE;
|
||||
open.HandleOut = &file;
|
||||
status = SysOpenFileAt(&open);
|
||||
if (!KSUCCESS(status)) return fail("open through resolved prefix", status);
|
||||
(void)SysCloseHandle(file);
|
||||
(void)SysCloseHandle(resolvedRoot);
|
||||
|
||||
// MODIFY resolution returns write authority without exporting RSSRV's private TRANSFER right.
|
||||
resolvedRoot = SYS_HANDLE_INVALID;
|
||||
resolvedLength = 0;
|
||||
status = NtlResourceResolve(session, SYS_SV_LITERAL("/SystemRoot/tests/resource_f.tmp"),
|
||||
NTL_RESOURCE_RESOLVE_FLAG_MODIFY,
|
||||
&resolvedRoot, &kind, &resolvedLength);
|
||||
if (!KSUCCESS(status) || kind != NTL_RESOURCE_KIND_VOLUME ||
|
||||
resolvedLength != sizeof("/SystemRoot") - 1u)
|
||||
return fail("resolve modify authority", status);
|
||||
|
||||
file = SYS_HANDLE_INVALID;
|
||||
memset(&open, 0, sizeof(open));
|
||||
open.Size = sizeof(open);
|
||||
open.RootHandle = resolvedRoot;
|
||||
open.Path = SYS_SV_LITERAL("tests/resource_f.tmp");
|
||||
open.Access = SYS_FILE_ACCESS_WRITE | SYS_FILE_ACCESS_QUERY;
|
||||
open.Disposition = SYS_FILE_CREATE_ALWAYS;
|
||||
open.Flags = SYS_FILE_FLAG_NONE;
|
||||
open.HandleOut = &file;
|
||||
status = SysOpenFileAt(&open);
|
||||
if (!KSUCCESS(status)) return fail("create through resolved modify root", status);
|
||||
(void)SysCloseHandle(file);
|
||||
|
||||
SYS_PATH_AT_REQUEST remove = { sizeof(remove), resolvedRoot, SYS_SV_LITERAL("tests/resource_f.tmp") };
|
||||
status = SysDeleteAt(&remove);
|
||||
if (!KSUCCESS(status)) return fail("delete through resolved modify root", status);
|
||||
(void)SysCloseHandle(resolvedRoot);
|
||||
|
||||
SYS_HANDLE overbroad = SYS_HANDLE_INVALID;
|
||||
status = NtlResourceLookup(session, SYS_SV_LITERAL("/SystemRoot"),
|
||||
SYS_RIGHT_QUERY | SYS_RIGHT_TRANSFER | SYS_VOLUME_RIGHT_OPEN, &overbroad);
|
||||
if (status != NTLSTATUS_ACCESS_DENIED || overbroad != SYS_HANDLE_INVALID)
|
||||
return fail("export-rights ceiling", status);
|
||||
|
||||
SYS_HANDLE missing = SYS_HANDLE_INVALID;
|
||||
status = NtlResourceLookup(session, SYS_SV_LITERAL("/Missing"), SYS_RIGHT_QUERY, &missing);
|
||||
if (status != NTLSTATUS_NOT_FOUND || missing != SYS_HANDLE_INVALID)
|
||||
return fail("missing lookup", status);
|
||||
|
||||
SYS_HANDLE event = SYS_HANDLE_INVALID;
|
||||
status = SysCreateEvent(0, 0, &event);
|
||||
if (!KSUCCESS(status)) return fail("create bind probe", status);
|
||||
status = NtlResourceBind(session, SYS_SV_LITERAL("/PublicBindMustFail"),
|
||||
NTL_RESOURCE_KIND_CAPABILITY, event,
|
||||
SYS_RIGHT_TRANSFER | SYS_RIGHT_QUERY, SYS_RIGHT_QUERY);
|
||||
(void)SysCloseHandle(event);
|
||||
if (status != NTLSTATUS_ACCESS_DENIED)
|
||||
return fail("public bind authority", status);
|
||||
|
||||
status = NtlResourceQuery(session, SYS_SV_LITERAL("/PublicBindMustFail"), &kind);
|
||||
if (status != NTLSTATUS_NOT_FOUND)
|
||||
return fail("rejected bind visibility", status);
|
||||
|
||||
status = NtlResourceQuery(session, SYS_SV_LITERAL("/SystemRoot/../Bad"), &kind);
|
||||
if (status != NTLSTATUS_INVALID_PARAMETER)
|
||||
return fail("canonical path rejection", status);
|
||||
|
||||
status = NtlResourceClose(session);
|
||||
if (!KSUCCESS(status)) return fail("close session", status);
|
||||
print("resource_service_smoke: PASS\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user