// Native smoke test for posixsrv discovery, stable PID registration, and bounded transactions. #include #include #include #include #include #include #include #include #include #include #define CHILD_ARGUMENT "--pid-child" static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } // Terminates the smoke test with one visible failure reason. static void fail(const char* text) { print("posix_service_smoke: "); print(text); print("\n"); for (;;) SysExitProcess(1); } // Returns whether the current command line contains one ASCII token. static bool command_contains(const char* token) { SYS_PEB* peb = SysGetPeb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION || !token) return false; size_t tokenLength = strlen(token); if (tokenLength == 0 || tokenLength > peb->CommandLine.Length) return false; for (size_t i = 0; i + tokenLength <= peb->CommandLine.Length; ++i) { if (memcmp(peb->CommandLine.Data + i, token, tokenLength) == 0) return true; } return false; } // Resolves /Services/posix through RSSRV and connects one independent client endpoint. static KSTATUS connect_posixsrv(SYS_HANDLE* endpointOut) { if (!endpointOut) return NTLSTATUS_INVALID_PARAMETER; *endpointOut = SYS_HANDLE_INVALID; SYS_HANDLE resource = SYS_HANDLE_INVALID; KSTATUS status = NtlResourceConnect(&resource); if (!KSUCCESS(status)) return status; SYS_HANDLE listener = SYS_HANDLE_INVALID; status = NtlResourceLookup(resource, SYS_SV_LITERAL(NTL_POSIX_SERVICE_PATH), SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT, &listener); (void)NtlResourceClose(resource); if (!KSUCCESS(status)) return status; SYS_CONNECT_PORT_REQUEST connect; memset(&connect, 0, sizeof(connect)); connect.Size = sizeof(connect); connect.ListenerHandle = listener; connect.Flags = SYS_PORT_CONNECT_FLAG_NONE; connect.EndpointHandleOut = endpointOut; status = SysConnectPort(&connect); (void)SysCloseHandle(listener); return status; } // Performs one fixed-size request with optional capability transfer and validates reply framing. static KSTATUS call_posixsrv_exchange(SYS_HANDLE endpoint, const NTL_POSIX_REQUEST* request, const SYS_PORT_HANDLE_TRANSFER* requestHandles, uint32_t requestHandleCount, SYS_HANDLE* replyHandlesOut, uint32_t replyHandleCapacity, uint32_t expectedReplyHandleCount, NTL_POSIX_REPLY* replyOut) { if (endpoint == SYS_HANDLE_INVALID || !request || !replyOut || expectedReplyHandleCount > replyHandleCapacity || (replyHandleCapacity != 0 && !replyHandlesOut)) return NTLSTATUS_INVALID_PARAMETER; memset(replyOut, 0, sizeof(*replyOut)); if (replyHandlesOut) { for (uint32_t i = 0; i < replyHandleCapacity; ++i) replyHandlesOut[i] = SYS_HANDLE_INVALID; } SYS_PORT_MESSAGE_INFO info; memset(&info, 0, sizeof(info)); info.Size = sizeof(info); SYS_CALL_PORT_REQUEST call; memset(&call, 0, sizeof(call)); call.Size = sizeof(call); call.EndpointHandle = endpoint; call.Flags = SYS_PORT_FLAG_NONE; call.RequestPayload = request; call.RequestLength = sizeof(*request); call.RequestHandles = requestHandles; call.RequestHandleCount = requestHandleCount; call.ReplyPayload = replyOut; call.ReplyCapacity = sizeof(*replyOut); call.ReplyHandlesOut = replyHandlesOut; call.ReplyHandleCapacity = replyHandleCapacity; call.ReplyInfoOut = &info; call.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; KSTATUS status = SysCallPort(&call); if (!KSUCCESS(status)) return status; uint32_t expectedHandles = KSUCCESS(replyOut->Status) ? expectedReplyHandleCount : 0u; if (info.Type != SYS_PORT_MESSAGE_REPLY || info.HandleCount != expectedHandles || info.PayloadLength != sizeof(*replyOut) || replyOut->Size != sizeof(*replyOut) || replyOut->Version != NTL_POSIX_PROTOCOL_VERSION || replyOut->Operation != request->Operation || replyOut->Flags != NTL_POSIX_REQUEST_FLAG_NONE) { if (replyHandlesOut) { uint32_t closeCount = info.HandleCount < replyHandleCapacity ? info.HandleCount : replyHandleCapacity; for (uint32_t i = 0; i < closeCount; ++i) { if (replyHandlesOut[i] != SYS_HANDLE_INVALID) (void)SysCloseHandle(replyHandlesOut[i]); replyHandlesOut[i] = SYS_HANDLE_INVALID; } } return NTLSTATUS_FAILURE; } return NTLSTATUS_SUCCESS; } // Performs one request that expects no capabilities in the reply. static KSTATUS call_posixsrv(SYS_HANDLE endpoint, const NTL_POSIX_REQUEST* request, const SYS_PORT_HANDLE_TRANSFER* handles, uint32_t handleCount, NTL_POSIX_REPLY* replyOut) { return call_posixsrv_exchange(endpoint, request, handles, handleCount, (SYS_HANDLE*)0, 0, 0, replyOut); } // Constructs the common fixed-size request header used by the service protocol. static NTL_POSIX_REQUEST make_request(uint32_t operation) { NTL_POSIX_REQUEST request; memset(&request, 0, sizeof(request)); request.Size = sizeof(request); request.Version = NTL_POSIX_PROTOCOL_VERSION; request.Operation = operation; request.Flags = NTL_POSIX_REQUEST_FLAG_NONE; return request; } // Registers the current native process through the accepted Port peer capability. static KSTATUS register_current_process(SYS_HANDLE endpoint, NTL_POSIX_REPLY* replyOut) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_REGISTER_PROCESS); size_t cwdRequired = 0; KSTATUS status = NtlGetCurrentDirectory(request.Path, sizeof(request.Path), &cwdRequired); if (!KSUCCESS(status)) return status; request.PathLength = (uint32_t)strlen(request.Path); return call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, replyOut); } // Provides a valid user APC target for protocol-level thread registration tests. static void __stdcall signal_probe_apc(void* context, void* argument1, void* argument2) { (void)context; (void)argument1; (void)argument2; } // Registers the current thread by transferring a restricted self capability. static KSTATUS register_current_thread(SYS_HANDLE endpoint, NTL_POSIX_REPLY* replyOut) { SYS_HANDLE self = SYS_HANDLE_INVALID; KSTATUS status = SysOpenCurrentThread(SYS_RIGHT_QUERY | SYS_RIGHT_TRANSFER | SYS_THREAD_RIGHT_NOTIFY, &self); if (!KSUCCESS(status)) return status; SYS_PORT_HANDLE_TRANSFER transfer; memset(&transfer, 0, sizeof(transfer)); transfer.Handle = self; transfer.DesiredRights = SYS_RIGHT_QUERY | SYS_THREAD_RIGHT_NOTIFY; transfer.Flags = SYS_PORT_TRANSFER_FLAG_NONE; NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_REGISTER_THREAD); request.SignalApcRoutine = (uint64_t)(uintptr_t)signal_probe_apc; status = call_posixsrv(endpoint, &request, &transfer, 1u, replyOut); (void)SysCloseHandle(self); return status; } // Unregisters the calling thread using the Port sender identity. static KSTATUS unregister_current_thread(SYS_HANDLE endpoint, NTL_POSIX_REPLY* replyOut) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_UNREGISTER_THREAD); KSTATUS status = call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, replyOut); if (!KSUCCESS(status)) return status; return replyOut->Status; } // Creates one handle-less server-owned description and returns its stable identity. static uint64_t create_synthetic_description(SYS_HANDLE endpoint, uint32_t type, uint32_t statusFlags, NTL_POSIX_REPLY* replyOut) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_CREATE_OPEN_DESCRIPTION); request.OpenDescriptionType = type; request.OpenStatusFlags = statusFlags; if (!KSUCCESS(call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, replyOut)) || !KSUCCESS(replyOut->Status) || replyOut->OpenDescriptionId == 0 || replyOut->SharedOpenDescription == 0) fail("shared description creation failed"); return replyOut->OpenDescriptionId; } // Releases one server-owned description held by the current registered process. static KSTATUS release_description(SYS_HANDLE endpoint, uint64_t descriptionId, NTL_POSIX_REPLY* replyOut) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_RELEASE_OPEN_DESCRIPTION); request.OpenDescriptionId = descriptionId; KSTATUS status = call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, replyOut); if (!KSUCCESS(status)) return status; return replyOut->Status; } typedef struct VFORK_SUBSTRATE_CONTEXT { SYS_HANDLE Endpoint; uint32_t ParentPid; uint32_t ChildPid; uint64_t Token; uint64_t FdToken; uint64_t DescriptionId; volatile uint32_t Result; } VFORK_SUBSTRATE_CONTEXT; // Attaches one native thread to a borrowed logical process and verifies routed FD ownership. static void vfork_substrate_thread(uintptr_t argument) { VFORK_SUBSTRATE_CONTEXT* context = (VFORK_SUBSTRATE_CONTEXT*)argument; if (!context) SysExitThread(1); SYS_HANDLE self = SYS_HANDLE_INVALID; KSTATUS status = SysOpenCurrentThread(SYS_RIGHT_QUERY | SYS_RIGHT_WAIT | SYS_RIGHT_DERIVE | SYS_RIGHT_TRANSFER | SYS_THREAD_RIGHT_NOTIFY, &self); if (!KSUCCESS(status)) { context->Result = 1u; SysExitThread(1); } SYS_PORT_HANDLE_TRANSFER transfer; memset(&transfer, 0, sizeof(transfer)); transfer.Handle = self; transfer.DesiredRights = SYS_RIGHT_QUERY | SYS_RIGHT_WAIT | SYS_RIGHT_DERIVE | SYS_THREAD_RIGHT_NOTIFY; NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_VFORK_ATTACH); request.TargetPosixPid = context->ChildPid; request.VforkToken = context->Token; request.SignalApcRoutine = (uint64_t)(uintptr_t)signal_probe_apc; NTL_POSIX_REPLY reply; status = call_posixsrv(context->Endpoint, &request, &transfer, 1u, &reply); (void)SysCloseHandle(self); if (!KSUCCESS(status) || !KSUCCESS(reply.Status) || reply.PosixPid != context->ChildPid || reply.ProcessState != NTL_POSIX_PROCESS_STATE_VFORK_BORROWED || reply.VforkToken != context->Token) { context->Result = 2u; SysExitThread(2); } request = make_request(NTL_POSIX_OP_GET_PROCESS_ATTRIBUTES); status = call_posixsrv(context->Endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply); if (!KSUCCESS(status) || !KSUCCESS(reply.Status) || reply.PosixPid != context->ChildPid || reply.ParentPosixPid != context->ParentPid || reply.ProcessState != NTL_POSIX_PROCESS_STATE_VFORK_BORROWED) { context->Result = 3u; SysExitThread(3); } request = make_request(NTL_POSIX_OP_IMPORT_FD_INHERITANCE); request.FdInheritanceToken = context->FdToken; request.FdInheritanceIndex = 0; status = call_posixsrv_exchange(context->Endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, (SYS_HANDLE*)0, 0, 0, &reply); if (!KSUCCESS(status) || !KSUCCESS(reply.Status) || reply.FdInheritanceCount != 1u || reply.FdDescriptionTotal != 1u || reply.FdDescriptionCount != 1u || reply.FdManifest[0].Descriptor != 7 || reply.FdManifest[0].OpenDescriptionId != context->DescriptionId || reply.FdDescriptions[0].OpenDescriptionId != context->DescriptionId) { context->Result = 4u; SysExitThread(4); } request = make_request(NTL_POSIX_OP_RELEASE_OPEN_DESCRIPTION); request.OpenDescriptionId = context->DescriptionId; status = call_posixsrv(context->Endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply); if (!KSUCCESS(status) || !KSUCCESS(reply.Status)) { context->Result = 5u; SysExitThread(5); } context->Result = 0u; SysExitThread(0); } // Exercises the server-owned borrowed-process record and sender-TID logical routing. static void test_vfork_substrate(SYS_HANDLE endpoint, uint32_t parentPid, uint64_t descriptionId, uint32_t baselineProcesses, uint32_t baselineThreads) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_CREATE_FD_INHERITANCE); request.FdInheritanceCount = 1u; request.FdManifest[0].Descriptor = 7; request.FdManifest[0].OpenDescriptionId = descriptionId; NTL_POSIX_REPLY reply; if (!KSUCCESS(call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.FdInheritanceToken == 0) fail("vfork descriptor snapshot failed"); uint64_t fdToken = reply.FdInheritanceToken; request = make_request(NTL_POSIX_OP_VFORK_BEGIN); request.FdInheritanceToken = fdToken; if (!KSUCCESS(call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.SpawnedPosixPid == 0 || reply.VforkToken == 0 || reply.RegisteredProcesses != baselineProcesses + 1u) fail("vfork borrowed child creation failed"); VFORK_SUBSTRATE_CONTEXT context; memset(&context, 0, sizeof(context)); context.Endpoint = endpoint; context.ParentPid = parentPid; context.ChildPid = reply.SpawnedPosixPid; context.Token = reply.VforkToken; context.FdToken = fdToken; context.DescriptionId = descriptionId; context.Result = UINT32_MAX; SYS_HANDLE thread = SYS_HANDLE_INVALID; uint32_t tid = 0; SYS_CREATE_THREAD_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Entry = (uintptr_t)vfork_substrate_thread; create.Argument = (uintptr_t)&context; create.Priority = 1u; create.ThreadHandleOut = &thread; create.ThreadIdOut = &tid; if (!KSUCCESS(SysCreateThread(&create)) || thread == SYS_HANDLE_INVALID || tid == 0) fail("vfork borrowed native thread creation failed"); if (!KSUCCESS(SysWait(thread, SYS_WAIT_FLAG_NONE))) fail("vfork borrowed native thread wait failed"); (void)SysCloseHandle(thread); if (context.Result != 0u) fail("vfork borrowed thread routing failed"); request = make_request(NTL_POSIX_OP_VFORK_CANCEL); request.TargetPosixPid = context.ChildPid; request.VforkToken = context.Token; if (!KSUCCESS(call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.RegisteredProcesses != baselineProcesses || reply.RegisteredThreads != baselineThreads) fail("vfork borrowed child cleanup failed"); } // Waits for the process monitor to retire one process and all of its shared holders. static void wait_registry_counts(SYS_HANDLE endpoint, uint32_t expectedProcesses, uint32_t expectedDescriptions) { for (uint32_t attempt = 0; attempt < 4096u; ++attempt) { NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_QUERY); NTL_POSIX_REPLY reply; if (!KSUCCESS(call_posixsrv(endpoint, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status)) fail("registry query failed"); if (reply.RegisteredProcesses == expectedProcesses && reply.RegisteredOpenDescriptions == expectedDescriptions) return; (void)SysYield(); } fail("exited process registry state was not retired"); } // Runs a second native process so the server must allocate a distinct stable POSIX PID. static uint32_t spawn_child_posix_pid(uint32_t* nativePidOut) { if (nativePidOut) *nativePidOut = 0; SYS_PEB* peb = SysGetPeb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION || !peb->ImagePath.Data || peb->ImagePath.Length == 0 || peb->ImagePath.Length > SYS_PATH_MAX) fail("invalid self image path"); char path[SYS_PATH_MAX + 1u]; memcpy(path, peb->ImagePath.Data, peb->ImagePath.Length); path[peb->ImagePath.Length] = '\0'; char command[SYS_PATH_MAX + 32u]; size_t pathLength = strlen(path); size_t argumentLength = strlen(CHILD_ARGUMENT); if (pathLength + 1u + argumentLength + 1u > sizeof(command)) fail("child command line too long"); memcpy(command, path, pathLength); command[pathLength] = ' '; memcpy(command + pathLength + 1u, CHILD_ARGUMENT, argumentLength + 1u); SYS_HANDLE process = SYS_HANDLE_INVALID; NTL_CREATE_SYSTEM_PROCESS_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Flags = NTL_PROCESS_LOAD_FLAG_NONE; create.ImageFile = SYS_HANDLE_INVALID; create.Path = SysSvFromCstr(path); create.CommandLine = SysSvFromCstr(command); create.SecurityContext = SYS_SECURITY_CONTEXT_CURRENT; create.ResolveModuleName = NtlResolveSystemModuleName; NTL_POSIX_BOOTSTRAP_DATA bootstrap; memset(&bootstrap, 0, sizeof(bootstrap)); bootstrap.Magic = NTL_POSIX_BOOTSTRAP_MAGIC; bootstrap.Version = NTL_POSIX_BOOTSTRAP_VERSION; bootstrap.Size = sizeof(bootstrap); create.StartupData = &bootstrap; create.StartupDataSize = sizeof(bootstrap); create.ProcessHandleOut = &process; KSTATUS status = NtlCreateSystemProcess(&create); if (!KSUCCESS(status)) fail("child process creation failed"); uint32_t nativePid = 0; if (!KSUCCESS(SysGetProcessPid(process, &nativePid))) fail("child native pid query failed"); if (nativePidOut) *nativePidOut = nativePid; if (!KSUCCESS(SysWait(process, SYS_WAIT_FLAG_NONE))) fail("child process wait failed"); int32_t exitCode = 0; if (!KSUCCESS(SysGetProcessExitCode(process, &exitCode))) fail("child exit query failed"); (void)SysCloseHandle(process); if (exitCode <= 0) fail("child returned invalid POSIX pid"); return (uint32_t)exitCode; } // Registers and returns the stable PID when running as the self-spawned child. static void run_child_mode(void) { NTL_POSIX_BOOTSTRAP_DATA bootstrap; size_t bootstrapSize = 0; if (!KSUCCESS(NtlGetProcessStartupData(&bootstrap, sizeof(bootstrap), &bootstrapSize)) || bootstrapSize != sizeof(bootstrap) || bootstrap.Magic != NTL_POSIX_BOOTSTRAP_MAGIC || bootstrap.Version != NTL_POSIX_BOOTSTRAP_VERSION || bootstrap.Size != sizeof(bootstrap) || bootstrap.Reserved != 0 || bootstrap.Token != 0 || bootstrap.PosixPid != 0 || bootstrap.Generation != 0 || bootstrap.FdInheritanceToken != 0) for (;;) SysExitProcess(4); SYS_HANDLE endpoint = SYS_HANDLE_INVALID; if (!KSUCCESS(connect_posixsrv(&endpoint))) for (;;) SysExitProcess(2); NTL_POSIX_REPLY reply; if (!KSUCCESS(register_current_process(endpoint, &reply)) || !KSUCCESS(reply.Status) || reply.PosixPid == 0 || reply.PosixPid > 0x7FFFFFFFu || reply.ProcessState != NTL_POSIX_PROCESS_STATE_RUNNING) for (;;) SysExitProcess(3); uint32_t pid = reply.PosixPid; NTL_POSIX_REPLY descriptionReply; uint64_t leakedDescription = create_synthetic_description( endpoint, NTL_POSIX_OPEN_TYPE_DEV_NULL, NTL_POSIX_OPEN_STATUS_WRONLY, &descriptionReply); NTL_POSIX_SHARED_OPEN_DESCRIPTION* shared = (NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)descriptionReply.SharedOpenDescription; if (leakedDescription == 0 || !shared || shared->DescriptionId != leakedDescription || shared->Magic != NTL_POSIX_SHARED_OPEN_MAGIC || shared->Version != NTL_POSIX_SHARED_OPEN_VERSION) for (;;) SysExitProcess(5); // Intentionally leak the holder; the server's native-process monitor must reclaim it. (void)SysDisconnectPort(endpoint); (void)SysCloseHandle(endpoint); for (;;) SysExitProcess((int32_t)pid); } // Exercises service discovery, stable identity, protocol versions, and transaction boundaries. int main(void) { if (command_contains(CHILD_ARGUMENT)) run_child_mode(); print("posix_service_smoke: start\n"); SYS_HANDLE first = SYS_HANDLE_INVALID; if (!KSUCCESS(connect_posixsrv(&first))) fail("first connect failed"); SYS_SECURITY_CONTEXT_INFO security; memset(&security, 0, sizeof(security)); security.Size = sizeof(security); if (!KSUCCESS(SysQuerySecurityContext(SYS_SECURITY_CONTEXT_CURRENT, &security))) fail("security query failed"); NTL_POSIX_REQUEST request = make_request(NTL_POSIX_OP_QUERY); NTL_POSIX_REPLY reply; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status)) fail("query failed"); if (reply.ClientProcessId != SysGetCurrentPid() || reply.ClientSecurityId != security.SecurityId || reply.ActiveTransactions != 0 || reply.TransactionCapacity != NTL_POSIX_TRANSACTION_CAPACITY || reply.PosixPid != 0) fail("pre-registration identity mismatch"); if (!KSUCCESS(register_current_process(first, &reply)) || !KSUCCESS(reply.Status)) fail("process registration failed"); uint32_t stablePid = reply.PosixPid; if (stablePid == 0 || stablePid == SysGetCurrentPid() || reply.NativeGeneration != 1u || reply.ProcessState != NTL_POSIX_PROCESS_STATE_RUNNING) fail("stable process identity mismatch"); if (reply.UserId != 0 || reply.EffectiveUserId != 0 || reply.GroupId != 0 || reply.EffectiveGroupId != 0 || reply.ProcessGroupId != stablePid || reply.SessionId != stablePid || reply.SupplementaryGroupCount != 0 || reply.NameLength != 4u || strcmp(reply.Name, "root") != 0) fail("initial shared process attributes mismatch"); char registeredCwd[SYS_PATH_MAX + 1u]; size_t registeredCwdRequired = 0; if (!KSUCCESS(NtlGetCurrentDirectory(registeredCwd, sizeof(registeredCwd), ®isteredCwdRequired)) || reply.CurrentDirectoryLength != strlen(registeredCwd) || strcmp(reply.CurrentDirectory, registeredCwd) != 0) fail("registered cwd mismatch"); uint32_t baselineProcesses = reply.RegisteredProcesses; uint32_t baselineDescriptions = reply.RegisteredOpenDescriptions; uint32_t baselineThreads = reply.RegisteredThreads; if (!KSUCCESS(register_current_thread(first, &reply)) || !KSUCCESS(reply.Status) || reply.RegisteredThreads != baselineThreads + 1u) fail("thread registration failed"); if (!KSUCCESS(register_current_thread(first, &reply)) || !KSUCCESS(reply.Status) || reply.RegisteredThreads != baselineThreads + 1u) fail("duplicate thread registration was not idempotent"); if (!KSUCCESS(unregister_current_thread(first, &reply)) || reply.RegisteredThreads != baselineThreads) fail("thread unregister failed"); if (unregister_current_thread(first, &reply) != NTLSTATUS_NOT_FOUND) fail("duplicate thread unregister was accepted"); NTL_POSIX_REPLY descriptionReply; uint64_t descriptionId = create_synthetic_description( first, NTL_POSIX_OPEN_TYPE_DEV_NULL, NTL_POSIX_OPEN_STATUS_WRONLY, &descriptionReply); if (descriptionReply.RegisteredOpenDescriptions != baselineDescriptions + 1u || descriptionReply.OpenDescriptionType != NTL_POSIX_OPEN_TYPE_DEV_NULL || descriptionReply.OpenStatusFlags != NTL_POSIX_OPEN_STATUS_WRONLY) fail("shared description registry mismatch"); NTL_POSIX_SHARED_OPEN_DESCRIPTION* shared = (NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)descriptionReply.SharedOpenDescription; if (!shared || shared->Magic != NTL_POSIX_SHARED_OPEN_MAGIC || shared->Version != NTL_POSIX_SHARED_OPEN_VERSION || shared->Type != NTL_POSIX_OPEN_TYPE_DEV_NULL || shared->DescriptionId != descriptionId || (uint32_t)shared->StatusFlags != NTL_POSIX_OPEN_STATUS_WRONLY) fail("shared description pointer mismatch"); request = make_request(NTL_POSIX_OP_SET_OPEN_STATUS); request.OpenDescriptionId = descriptionId; request.OpenStatusFlags = NTL_POSIX_OPEN_STATUS_WRONLY | NTL_POSIX_OPEN_STATUS_NONBLOCK; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &descriptionReply)) || !KSUCCESS(descriptionReply.Status) || descriptionReply.OpenDescriptionId != descriptionId || descriptionReply.OpenStatusFlags != request.OpenStatusFlags || (uint32_t)shared->StatusFlags != request.OpenStatusFlags) fail("server-serialized status update failed"); test_vfork_substrate(first, stablePid, descriptionId, baselineProcesses, baselineThreads); if (!KSUCCESS(release_description(first, descriptionId, &descriptionReply)) || descriptionReply.RegisteredOpenDescriptions != baselineDescriptions) fail("shared description release failed"); if (release_description(first, descriptionId, &descriptionReply) != NTLSTATUS_NOT_FOUND) fail("duplicate shared description release was accepted"); request = make_request(NTL_POSIX_OP_CREATE_PIPE); SYS_HANDLE pipeHandles[2] = { SYS_HANDLE_INVALID, SYS_HANDLE_INVALID }; if (!KSUCCESS(call_posixsrv_exchange(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, pipeHandles, 2u, 2u, &descriptionReply)) || !KSUCCESS(descriptionReply.Status) || descriptionReply.RegisteredOpenDescriptions != baselineDescriptions + 2u || descriptionReply.OpenDescriptionType != NTL_POSIX_OPEN_TYPE_PIPE_READ || descriptionReply.OpenDescriptionType2 != NTL_POSIX_OPEN_TYPE_PIPE_WRITE || descriptionReply.OpenStatusFlags != NTL_POSIX_OPEN_STATUS_RDONLY || descriptionReply.OpenStatusFlags2 != NTL_POSIX_OPEN_STATUS_WRONLY || descriptionReply.OpenDescriptionId == 0 || descriptionReply.OpenDescriptionId2 == 0 || descriptionReply.OpenDescriptionId == descriptionReply.OpenDescriptionId2 || pipeHandles[0] == SYS_HANDLE_INVALID || pipeHandles[1] == SYS_HANDLE_INVALID) fail("server-owned pipe creation failed"); NTL_POSIX_SHARED_OPEN_DESCRIPTION* pipeReadShared = (NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)descriptionReply.SharedOpenDescription; NTL_POSIX_SHARED_OPEN_DESCRIPTION* pipeWriteShared = (NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)descriptionReply.SharedOpenDescription2; SYS_PIPE_SHARED_STATE* pipeShared = pipeReadShared ? (SYS_PIPE_SHARED_STATE*)(uintptr_t)pipeReadShared->SharedObjectData : (SYS_PIPE_SHARED_STATE*)0; if (!pipeReadShared || !pipeWriteShared || !pipeShared || pipeReadShared->Magic != NTL_POSIX_SHARED_OPEN_MAGIC || pipeWriteShared->Magic != NTL_POSIX_SHARED_OPEN_MAGIC || pipeReadShared->Version != NTL_POSIX_SHARED_OPEN_VERSION || pipeWriteShared->Version != NTL_POSIX_SHARED_OPEN_VERSION || pipeReadShared->DescriptionId != descriptionReply.OpenDescriptionId || pipeWriteShared->DescriptionId != descriptionReply.OpenDescriptionId2 || pipeReadShared->SharedObjectData != pipeWriteShared->SharedObjectData || pipeShared->Magic != SYS_PIPE_SHARED_MAGIC || pipeShared->Version != SYS_PIPE_SHARED_VERSION || pipeShared->Capacity != SYS_PIPE_BUFFER_CAPACITY || pipeShared->HeaderBytes != SYS_PIPE_SHARED_HEADER_BYTES || pipeShared->ReaderOpen == 0 || pipeShared->WriterOpen == 0) fail("server-owned pipe shared state mismatch"); if (!KSUCCESS(release_description(first, descriptionReply.OpenDescriptionId, &reply)) || reply.RegisteredOpenDescriptions != baselineDescriptions + 1u || pipeShared->ReaderOpen == 0) fail("pipe read master release invalidated live alias"); if (!KSUCCESS(SysCloseHandle(pipeHandles[0])) || pipeShared->ReaderOpen != 0) fail("pipe read alias close did not publish reader shutdown"); pipeHandles[0] = SYS_HANDLE_INVALID; if (!KSUCCESS(SysCloseHandle(pipeHandles[1]))) fail("pipe write alias close failed"); pipeHandles[1] = SYS_HANDLE_INVALID; if (!KSUCCESS(release_description(first, descriptionReply.OpenDescriptionId2, &reply)) || reply.RegisteredOpenDescriptions != baselineDescriptions) fail("server-owned pipe description release failed"); request = make_request(NTL_POSIX_OP_LOOKUP_USER); request.LookupKind = NTL_POSIX_LOOKUP_BY_NAME; memcpy(request.Name, "user", 5u); request.NameLength = 4u; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.UserId != 1000u || reply.GroupId != 1000u || strcmp(reply.Name, "user") != 0) fail("identity database lookup failed"); uint32_t childNativePid = 0; uint32_t childPosixPid = spawn_child_posix_pid(&childNativePid); if (childPosixPid == stablePid || childPosixPid == childNativePid) fail("child POSIX identity was not independent"); wait_registry_counts(first, 1u, baselineDescriptions); request = make_request(NTL_POSIX_OP_BEGIN_TRANSACTION); request.TransactionKind = NTL_POSIX_TRANSACTION_SPAWN; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.TransactionId == 0 || reply.ActiveTransactions != 1) fail("transaction begin failed"); uint32_t transactionId = reply.TransactionId; SYS_HANDLE second = SYS_HANDLE_INVALID; if (!KSUCCESS(connect_posixsrv(&second))) fail("second connect failed"); if (!KSUCCESS(register_current_process(second, &reply)) || !KSUCCESS(reply.Status) || reply.PosixPid != stablePid || reply.NativeGeneration != 1u) fail("same-process reconnect changed POSIX identity"); request = make_request(NTL_POSIX_OP_QUERY); if (!KSUCCESS(call_posixsrv(second, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.ActiveTransactions != 1 || reply.PosixPid != stablePid) fail("process transaction sharing failed"); request = make_request(NTL_POSIX_OP_QUERY); request.Version = NTL_POSIX_PROTOCOL_VERSION + 1u; if (!KSUCCESS(call_posixsrv(second, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || reply.Status != NTLSTATUS_NOT_SUPPORTED) fail("version rejection failed"); request = make_request(NTL_POSIX_OP_CANCEL_TRANSACTION); request.TransactionId = transactionId; if (!KSUCCESS(call_posixsrv(second, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.TransactionId != transactionId || reply.ActiveTransactions != 0) fail("cross-connection transaction cancel failed"); request = make_request(NTL_POSIX_OP_CANCEL_TRANSACTION); request.TransactionId = transactionId; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || reply.Status != NTLSTATUS_NOT_FOUND) fail("unknown transaction rejection failed"); request = make_request(NTL_POSIX_OP_BEGIN_TRANSACTION); request.TransactionKind = NTL_POSIX_TRANSACTION_EXEC; if (!KSUCCESS(call_posixsrv(first, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.TransactionId == 0 || reply.ActiveTransactions != 1) fail("exec transaction begin failed"); uint32_t reconnectTransactionId = reply.TransactionId; (void)SysDisconnectPort(first); (void)SysCloseHandle(first); (void)SysDisconnectPort(second); (void)SysCloseHandle(second); SYS_HANDLE third = SYS_HANDLE_INVALID; if (!KSUCCESS(connect_posixsrv(&third))) fail("reconnect failed"); if (!KSUCCESS(register_current_process(third, &reply)) || !KSUCCESS(reply.Status) || reply.PosixPid != stablePid || reply.NativeGeneration != 1u || reply.ActiveTransactions != 1) fail("live process lost process-owned transaction after disconnect"); request = make_request(NTL_POSIX_OP_CANCEL_TRANSACTION); request.TransactionId = reconnectTransactionId; if (!KSUCCESS(call_posixsrv(third, &request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, &reply)) || !KSUCCESS(reply.Status) || reply.ActiveTransactions != 0) fail("reconnected transaction cancel failed"); (void)SysDisconnectPort(third); (void)SysCloseHandle(third); print("posix_service_smoke: PASS\n"); return 0; }