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

201 lines
8.5 KiB
C

// 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;
}