[+] Arg0 to AuProcesses::StartupParameters::posixApplySandboxCOW, and return bool to fail.

[+] A fail fast IO mechanism underneath AuProcesses::IProcess (POSIX) to notify a failure within the 250ms timeout period / Hardened logic that would just crash
This commit is contained in:
Reece Wilson 2024-12-14 19:39:15 +00:00
parent a084105267
commit 6b0ca15cdb
3 changed files with 98 additions and 7 deletions

View File

@ -101,7 +101,18 @@ namespace Aurora::Processes
bool bForceNoJobParent {}; bool bForceNoJobParent {};
#endif #endif
#if defined(AURORA_IS_POSIX_DERIVED) #if defined(AURORA_IS_POSIX_DERIVED)
AuVoidFunc posixApplySandboxCOW; // Called after fork, before exec, and just before the parent process is signaled with the OK semaphore.
// Use this opportunity to apply sandboxing, additional isolation, or pinning rules.
//
// You may access properties bound to the function (AuBind); however, you are subject to COW rules.
//
// If you must allocate, use the freshly mmap'd memory heap provided to you in arg0, and dont call any crt or
// external library function that'll probably call the system allocator.
//
// Every IO fd you once knew should be considered dead. Every heap and mutex could be in use by another process.
// Should parent fds or heap allocators be accessible, you should assume this is under a race condition or
// an implementation detail subject to change.
AuSupplierConsumer<bool, AuHeap *> posixApplySandboxCOW;
AuVoidFunc posixPCA; AuVoidFunc posixPCA;
AuVoidFunc posixPCB; AuVoidFunc posixPCB;
#endif #endif

View File

@ -467,6 +467,29 @@ namespace Aurora::Processes
} }
} }
this->pSemaphoreError_ = AuLoop::NewLSSemaphoreSlow(0);
if (!this->pSemaphoreError_)
{
SysPushErrorIO("No sync");
return false;
}
{
auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphoreError_);
int iFlags = fcntl(semaphoreFd, F_GETFD, 0);
if (iFlags < 0)
{
SysPushErrorIO("fcntl error");
return false;
}
iFlags &= ~FD_CLOEXEC;
if (fcntl(semaphoreFd, F_SETFD, iFlags) < 0)
{
SysPushErrorIO("fcntl error");
return false;
}
}
this->finished_ = AuThreadPrimitives::EventShared(false, false, true); this->finished_ = AuThreadPrimitives::EventShared(false, false, true);
if (!this->finished_) if (!this->finished_)
{ {
@ -581,6 +604,23 @@ namespace Aurora::Processes
return {}; return {};
} }
void ProcessImpl::ForkFail()
{
{
auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphoreError_);
this->pSemaphore_->AddOne();
close(semaphoreFd);
}
{
auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphore_);
this->pSemaphore_->AddOne();
close(semaphoreFd);
}
PosixFDYeetus();
}
void ProcessImpl::ForkMain() void ProcessImpl::ForkMain()
{ {
PosixDoForkHooks(); PosixDoForkHooks();
@ -591,8 +631,10 @@ namespace Aurora::Processes
auto pHeapMemory = SysAllocateLarge(kForkMemSize); auto pHeapMemory = SysAllocateLarge(kForkMemSize);
if (!pHeapMemory) if (!pHeapMemory)
{ {
this->ForkFail();
return; return;
} }
AuMemoryViewWrite heapView { pHeapMemory, kForkMemSize }; AuMemoryViewWrite heapView { pHeapMemory, kForkMemSize };
AuMemory::RequestHeapOfRegion heapObject(heapView); AuMemory::RequestHeapOfRegion heapObject(heapView);
@ -693,21 +735,34 @@ namespace Aurora::Processes
#endif #endif
} }
if (this->startup_.posixApplySandboxCOW) auto pProcessPath = heapObject->ZAlloc<char *>(this->startup_.process.size() + 1);
if (!pProcessPath)
{ {
this->startup_.posixApplySandboxCOW(); this->ForkFail();
return;
} }
auto pProcessPath = heapObject->ZAlloc<char *>(this->startup_.process.size() + 1);
AuMemcpy(pProcessPath, this->startup_.process.c_str(), this->startup_.process.size()); AuMemcpy(pProcessPath, this->startup_.process.c_str(), this->startup_.process.size());
auto pArgsBlock = heapObject->ZAlloc<void **>((this->cargs_.size() + 1) * sizeof(void *)); auto pArgsBlock = heapObject->ZAlloc<void **>((this->cargs_.size() + 1) * sizeof(void *));
if (!pArgsBlock)
{
this->ForkFail();
return;
}
for (AU_ITERATE_N(i, this->cargs_.size())) for (AU_ITERATE_N(i, this->cargs_.size()))
{ {
if (auto pString = this->cargs_[i]) if (auto pString = this->cargs_[i])
{ {
auto uLength = strlen(pString) + 1; auto uLength = strlen(pString) + 1;
auto pArg = heapObject->ZAlloc<char *>(uLength); auto pArg = heapObject->ZAlloc<char *>(uLength);
if (!pArg)
{
this->ForkFail();
return;
}
AuMemcpy(pArg, pString, uLength); AuMemcpy(pArg, pString, uLength);
pArgsBlock[i] = pArg; pArgsBlock[i] = pArg;
} }
@ -719,12 +774,27 @@ namespace Aurora::Processes
auto &[key, value] = this->startup_.environmentVariables[i]; auto &[key, value] = this->startup_.environmentVariables[i];
auto uLength = key.size() + value.size() + 2; auto uLength = key.size() + value.size() + 2;
auto pArg = heapObject->ZAlloc<char *>(uLength); auto pArg = heapObject->ZAlloc<char *>(uLength);
if (!pArg)
{
this->ForkFail();
return;
}
AuMemcpy(pArg, key.data(), key.size()); AuMemcpy(pArg, key.data(), key.size());
pArg[key.size()] = '='; pArg[key.size()] = '=';
AuMemcpy(pArg + key.size() + 1, value.data(), value.size()); AuMemcpy(pArg + key.size() + 1, value.data(), value.size());
pEnvArgsBlock[i] = pArg; pEnvArgsBlock[i] = pArg;
} }
if (this->startup_.posixApplySandboxCOW)
{
if (!this->startup_.posixApplySandboxCOW(heapObject.AsPointer()))
{
this->ForkFail();
return;
}
}
// Send an OK signal to the parent // Send an OK signal to the parent
{ {
auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphore_); auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphore_);
@ -732,6 +802,11 @@ namespace Aurora::Processes
close(semaphoreFd); close(semaphoreFd);
} }
{
auto semaphoreFd = AuLoop::DbgLoopSourceToReadFd(this->pSemaphoreError_);
close(semaphoreFd);
}
// `this` is now trash // `this` is now trash
// On platforms that support it, eradicate all fds above our standard pipes regardless of close on exec status // On platforms that support it, eradicate all fds above our standard pipes regardless of close on exec status
@ -797,7 +872,8 @@ namespace Aurora::Processes
SysAssert(AuTryInsert(gPidLookupMap, pid, this)); SysAssert(AuTryInsert(gPidLookupMap, pid, this));
} }
return this->pSemaphore_->WaitOn(250); return this->pSemaphore_->WaitOn(250) &&
!this->pSemaphoreError_->IsSignaled();
} }
else else
{ {

View File

@ -69,6 +69,9 @@ namespace Aurora::Processes
void ForkMain(); void ForkMain();
void HookMainDeath(); void HookMainDeath();
void ForkFail();
private: private:
int pipeStdOut_[2] { -1, -1 }; int pipeStdOut_[2] { -1, -1 };
@ -102,6 +105,7 @@ namespace Aurora::Processes
bool bHasExited {}; bool bHasExited {};
AuSPtr<AuLoop::ILSSemaphore> pSemaphore_; AuSPtr<AuLoop::ILSSemaphore> pSemaphore_;
AuSPtr<AuLoop::ILSSemaphore> pSemaphoreError_;
AuSPtr<IO::CompletionGroup::ICompletionGroup> pCompletionGroup_; AuSPtr<IO::CompletionGroup::ICompletionGroup> pCompletionGroup_;
}; };