[*] Introduce APIs to access IProcessSectionMapView safely when malicious calls to Unmap could be made

This commit is contained in:
Reece Wilson 2024-04-12 13:12:35 +01:00
parent f589227c1d
commit 3115627424
6 changed files with 145 additions and 53 deletions

View File

@ -79,6 +79,32 @@ namespace Aurora::Memory
this->controlBlock.pPinner = view.controlBlock.pPinner;
}
MemoryView(const MemoryView &view, const AuSPtr<void> &pThat)
{
this->ptr = view.ptr;
this->length = view.length;
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
if (this->controlBlock.pInUseCounter)
{
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
}
if (view.controlBlock.pPinner)
{
auto pThat2 = AuMakeSharedArray<AuSPtr<void>>(2);
this->controlBlock.pPinner = pThat2;
if (!this->controlBlock.pPinner)
{
AuMemoryPanic("OOM");
}
pThat2.get()[0] = pThat;
pThat2.get()[1] = view.controlBlock.pPinner;
}
else
{
this->controlBlock.pPinner = pThat;
}
}
MemoryView(MemoryView &&view)
{
this->ptr = view.ptr;
@ -280,7 +306,9 @@ namespace Aurora::Memory
{
if (uOffset < this->uLength)
{
return MemoryView(this->pBase + uOffset, this->uLength - uOffset, this->controlBlock);
return MemoryView((AuUInt8 *)this->pBase + uOffset,
this->uLength - uOffset,
this->controlBlock);
}
else
{
@ -292,7 +320,9 @@ namespace Aurora::Memory
{
if (uLength <= this->uLength)
{
return MemoryView(this->pBase, uLength, this->controlBlock);
return MemoryView((AuUInt8 *)this->pBase,
uLength,
this->controlBlock);
}
else
{

View File

@ -13,13 +13,16 @@ namespace Aurora::Process
{
virtual void Unmap() = 0;
virtual bool Flush(AuUInt offset, AuUInt length) = 0;
virtual bool Flush(AuUInt uOffset, AuUInt uLength) = 0;
virtual AuUInt GetBaseAddress() = 0;
virtual AuUInt GetAddress(AuUInt offset) = 0;
virtual AuUInt GetAddress(AuUInt uOffset) = 0;
virtual AuUInt8 *GetBasePointer() = 0;
virtual AuUInt8 *GetPointer(AuUInt offset) = 0;
virtual AuUInt8 *GetPointer(AuUInt uOffset) = 0;
virtual Memory::MemoryViewWrite ToWriteView() = 0;
virtual Memory::MemoryViewRead ToReadView() = 0;
virtual bool LockSwap() = 0;
virtual bool UnlockSwap() = 0;

View File

@ -12,26 +12,35 @@
namespace Aurora::Process
{
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress,
HANDLE hSection) :
uAddress_(uAddress),
hFileSection(hSection)
{
}
ProcessSectionFileMapView::~ProcessSectionFileMapView()
{
Unmap();
}
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress, HANDLE hSection) :
uAddress(uAddress),
hFileSection(hSection)
{
}
void ProcessSectionFileMapView::Unmap()
{
AU_LOCK_GUARD(this->mutex_);
if (AuAtomicLoad(&this->uInUse_))
{
SysPushErrorResourceLocked("Cannot unmap memory while it's in use");
return;
}
if (AuExchange(this->bIsDead_, true))
{
return;
}
if (this->uAddress)
if (this->uAddress_)
{
if (this->pSharedSectionHint)
{
@ -39,9 +48,9 @@ namespace Aurora::Process
}
else
{
::UnmapViewOfFile((PVOID)this->uAddress);
::UnmapViewOfFile((PVOID)this->uAddress_);
}
this->uAddress = 0;
this->uAddress_ = 0;
}
AuWin32CloseHandle(this->hFileSection);
@ -49,48 +58,62 @@ namespace Aurora::Process
this->pProcessGlobalHint = nullptr;
}
bool ProcessSectionFileMapView::Flush(AuUInt offset, AuUInt length)
bool ProcessSectionFileMapView::Flush(AuUInt uOffset, AuUInt uLength)
{
return ::FlushViewOfFile(this->GetPointer(offset), length);
return ::FlushViewOfFile(this->GetPointer(uOffset), uLength);
}
AuMemoryViewWrite ProcessSectionFileMapView::ToWriteView()
{
return AuMemoryViewWrite((char *)this->uAddress_, this->uLength, &this->uInUse_);
}
AuMemoryViewRead ProcessSectionFileMapView::ToReadView()
{
return AuMemoryViewRead((char *)this->uAddress_, this->uLength, &this->uInUse_);
}
AuUInt ProcessSectionFileMapView::GetBaseAddress()
{
return this->uAddress;
return this->uAddress_;
}
AuUInt ProcessSectionFileMapView::GetAddress(AuUInt offset)
AuUInt ProcessSectionFileMapView::GetAddress(AuUInt uOffset)
{
return this->uAddress ? this->uAddress + offset : 0;
return this->uAddress_ && this->uLength > uOffset ?
this->uAddress_ + uOffset :
0;
}
AuUInt8 *ProcessSectionFileMapView::GetBasePointer()
{
return AuReinterpretCast<AuUInt8 *>(this->uAddress);
return AuReinterpretCast<AuUInt8 *>(this->uAddress_);
}
AuUInt8 *ProcessSectionFileMapView::GetPointer(AuUInt offset)
AuUInt8 *ProcessSectionFileMapView::GetPointer(AuUInt uOffset)
{
return this->uAddress ? AuReinterpretCast<AuUInt8 *>(this->uAddress) + offset : 0;
return this->uAddress_ && this->uLength > uOffset ?
AuReinterpretCast<AuUInt8 *>(this->uAddress_) + uOffset :
0;
}
bool ProcessSectionFileMapView::LockSwap()
{
if (!this->uAddress)
if (!this->uAddress_)
{
return false;
}
return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength} });
return AuMemory::SwapLock::Lock({ { this->uAddress_, this->uLength } });
}
bool ProcessSectionFileMapView::UnlockSwap()
{
if (!this->uAddress)
if (!this->uAddress_)
{
return false;
}
return AuMemory::SwapLock::Unlock({ { this->uAddress, this->uLength} });
return AuMemory::SwapLock::Unlock({ { this->uAddress_, this->uLength } });
}
}

View File

@ -18,13 +18,16 @@ namespace Aurora::Process
void Unmap() override;
bool Flush(AuUInt offset, AuUInt length) override;
bool Flush(AuUInt uOffset, AuUInt uLength) override;
AuUInt GetBaseAddress() override;
AuUInt GetAddress(AuUInt offset) override;
AuUInt GetAddress(AuUInt uOffset) override;
AuUInt8 *GetBasePointer() override;
AuUInt8 *GetPointer(AuUInt offset) override;
AuUInt8 *GetPointer(AuUInt uOffset) override;
Memory::MemoryViewWrite ToWriteView() override;
Memory::MemoryViewRead ToReadView() override;
bool LockSwap() override;
bool UnlockSwap() override;
@ -36,7 +39,9 @@ namespace Aurora::Process
private:
HANDLE hFileSection {};
AuUInt uAddress {};
AuUInt uAddress_ {};
AuAUInt32 uInUse_ {};
AuMutex mutex_;
bool bIsDead_ {};
};

View File

@ -13,8 +13,11 @@
namespace Aurora::Process
{
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress, AuUInt uLength, bool bShouldUnmap, int optFd) :
uAddress(uAddress),
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress,
AuUInt uLength,
bool bShouldUnmap,
int optFd) :
uAddress_(uAddress),
uLength_(uLength),
bShouldUnmap_(bShouldUnmap),
optFd_(optFd)
@ -29,16 +32,24 @@ namespace Aurora::Process
void ProcessSectionFileMapView::Unmap()
{
AU_LOCK_GUARD(this->mutex_);
if (AuAtomicLoad(&this->uInUse_))
{
SysPushErrorResourceLocked("Cannot unmap memory while it's in use");
return;
}
if (AuExchange(this->bIsDead_, true))
{
return;
}
if (this->uAddress)
if (this->uAddress_)
{
if (this->pSharedSectionHint)
{
AuStaticCast<ProcessSectionViewReserved>(this->pSharedSectionHint)->Release(this->uAddress);
AuStaticCast<ProcessSectionViewReserved>(this->pSharedSectionHint)->Release(this->uAddress_);
}
if (this->bShouldUnmap_)
@ -53,9 +64,10 @@ namespace Aurora::Process
}
}
this->uAddress = 0;
this->uAddress_ = 0;
}
// TODO: posix explicitly states this isnt necessary
int fd {-1};
if ((fd = AuExchange(this->optFd_, -1)) != -1)
{
@ -63,48 +75,62 @@ namespace Aurora::Process
}
}
bool ProcessSectionFileMapView::Flush(AuUInt offset, AuUInt length)
bool ProcessSectionFileMapView::Flush(AuUInt uOffset, AuUInt uLength)
{
return ::msync(this->GetPointer(offset), length, MS_SYNC) == 0;
return ::msync(this->GetPointer(uOffset), uLength, MS_SYNC) == 0;
}
AuMemoryViewWrite ProcessSectionFileMapView::ToWriteView()
{
return AuMemoryViewWrite((char *)this->uAddress_, this->uLength_, &this->uInUse_);
}
AuMemoryViewRead ProcessSectionFileMapView::ToReadView()
{
return AuMemoryViewRead((char *)this->uAddress_, this->uLength_, &this->uInUse_);
}
AuUInt ProcessSectionFileMapView::GetBaseAddress()
{
return this->uAddress;
return this->uAddress_;
}
AuUInt ProcessSectionFileMapView::GetAddress(AuUInt offset)
AuUInt ProcessSectionFileMapView::GetAddress(AuUInt uOffset)
{
return this->uAddress ? this->uAddress + offset : 0;
return this->uAddress_ && this->uLength_ > uOffset ?
this->uAddress_ + uOffset :
0;
}
AuUInt8 *ProcessSectionFileMapView::GetBasePointer()
{
return AuReinterpretCast<AuUInt8 *>(this->uAddress);
return AuReinterpretCast<AuUInt8 *>(this->uAddress_);
}
AuUInt8 *ProcessSectionFileMapView::GetPointer(AuUInt offset)
AuUInt8 *ProcessSectionFileMapView::GetPointer(AuUInt uOffset)
{
return this->uAddress ? AuReinterpretCast<AuUInt8 *>(this->uAddress) + offset : 0;
return this->uAddress_ && this->uLength_ > uOffset ?
AuReinterpretCast<AuUInt8 *>(this->uAddress_) + uOffset :
0;
}
bool ProcessSectionFileMapView::LockSwap()
{
if (!this->uAddress)
if (!this->uAddress_)
{
return false;
}
return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength_ } });
return AuMemory::SwapLock::Lock({ { this->uAddress_, this->uLength_ } });
}
bool ProcessSectionFileMapView::UnlockSwap()
{
if (!this->uAddress)
if (!this->uAddress_)
{
return false;
}
return AuMemory::SwapLock::Unlock({ { this->uAddress, this->uLength_ } });
return AuMemory::SwapLock::Unlock({ { this->uAddress_, this->uLength_ } });
}
}

View File

@ -18,13 +18,16 @@ namespace Aurora::Process
void Unmap() override;
bool Flush(AuUInt offset, AuUInt length) override;
bool Flush(AuUInt uOffset, AuUInt uLength) override;
AuUInt GetBaseAddress() override;
AuUInt GetAddress(AuUInt offset) override;
AuUInt GetAddress(AuUInt uOffset) override;
AuUInt8 *GetBasePointer() override;
AuUInt8 *GetPointer(AuUInt offset) override;
AuUInt8 *GetPointer(AuUInt uOffset) override;
Memory::MemoryViewWrite ToWriteView() override;
Memory::MemoryViewRead ToReadView() override;
AuSPtr<IProcessSectionView> pSharedSectionHint {};
@ -32,8 +35,10 @@ namespace Aurora::Process
bool UnlockSwap() override;
private:
AuUInt uAddress {};
AuUInt uAddress_ {};
AuUInt uLength_ {};
AuMutex mutex_;
AuAUInt32 uInUse_ {};
bool bShouldUnmap_ {};
int optFd_ {-1};
bool bIsDead_ {};