[*] 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; 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) MemoryView(MemoryView &&view)
{ {
this->ptr = view.ptr; this->ptr = view.ptr;
@ -280,7 +306,9 @@ namespace Aurora::Memory
{ {
if (uOffset < this->uLength) 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 else
{ {
@ -292,7 +320,9 @@ namespace Aurora::Memory
{ {
if (uLength <= this->uLength) if (uLength <= this->uLength)
{ {
return MemoryView(this->pBase, uLength, this->controlBlock); return MemoryView((AuUInt8 *)this->pBase,
uLength,
this->controlBlock);
} }
else else
{ {

View File

@ -13,13 +13,16 @@ namespace Aurora::Process
{ {
virtual void Unmap() = 0; 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 GetBaseAddress() = 0;
virtual AuUInt GetAddress(AuUInt offset) = 0; virtual AuUInt GetAddress(AuUInt uOffset) = 0;
virtual AuUInt8 *GetBasePointer() = 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 LockSwap() = 0;
virtual bool UnlockSwap() = 0; virtual bool UnlockSwap() = 0;

View File

@ -12,26 +12,35 @@
namespace Aurora::Process namespace Aurora::Process
{ {
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress,
HANDLE hSection) :
uAddress_(uAddress),
hFileSection(hSection)
{
}
ProcessSectionFileMapView::~ProcessSectionFileMapView() ProcessSectionFileMapView::~ProcessSectionFileMapView()
{ {
Unmap(); Unmap();
} }
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress, HANDLE hSection) :
uAddress(uAddress),
hFileSection(hSection)
{
}
void ProcessSectionFileMapView::Unmap() 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)) if (AuExchange(this->bIsDead_, true))
{ {
return; return;
} }
if (this->uAddress) if (this->uAddress_)
{ {
if (this->pSharedSectionHint) if (this->pSharedSectionHint)
{ {
@ -39,9 +48,9 @@ namespace Aurora::Process
} }
else else
{ {
::UnmapViewOfFile((PVOID)this->uAddress); ::UnmapViewOfFile((PVOID)this->uAddress_);
} }
this->uAddress = 0; this->uAddress_ = 0;
} }
AuWin32CloseHandle(this->hFileSection); AuWin32CloseHandle(this->hFileSection);
@ -49,48 +58,62 @@ namespace Aurora::Process
this->pProcessGlobalHint = nullptr; 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() 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() 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() bool ProcessSectionFileMapView::LockSwap()
{ {
if (!this->uAddress) if (!this->uAddress_)
{ {
return false; return false;
} }
return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength} }); return AuMemory::SwapLock::Lock({ { this->uAddress_, this->uLength } });
} }
bool ProcessSectionFileMapView::UnlockSwap() bool ProcessSectionFileMapView::UnlockSwap()
{ {
if (!this->uAddress) if (!this->uAddress_)
{ {
return false; 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; void Unmap() override;
bool Flush(AuUInt offset, AuUInt length) override; bool Flush(AuUInt uOffset, AuUInt uLength) override;
AuUInt GetBaseAddress() override; AuUInt GetBaseAddress() override;
AuUInt GetAddress(AuUInt offset) override; AuUInt GetAddress(AuUInt uOffset) override;
AuUInt8 *GetBasePointer() 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 LockSwap() override;
bool UnlockSwap() override; bool UnlockSwap() override;
@ -36,7 +39,9 @@ namespace Aurora::Process
private: private:
HANDLE hFileSection {}; HANDLE hFileSection {};
AuUInt uAddress {}; AuUInt uAddress_ {};
AuAUInt32 uInUse_ {};
AuMutex mutex_;
bool bIsDead_ {}; bool bIsDead_ {};
}; };

View File

@ -13,8 +13,11 @@
namespace Aurora::Process namespace Aurora::Process
{ {
ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress, AuUInt uLength, bool bShouldUnmap, int optFd) : ProcessSectionFileMapView::ProcessSectionFileMapView(AuUInt uAddress,
uAddress(uAddress), AuUInt uLength,
bool bShouldUnmap,
int optFd) :
uAddress_(uAddress),
uLength_(uLength), uLength_(uLength),
bShouldUnmap_(bShouldUnmap), bShouldUnmap_(bShouldUnmap),
optFd_(optFd) optFd_(optFd)
@ -29,16 +32,24 @@ namespace Aurora::Process
void ProcessSectionFileMapView::Unmap() 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)) if (AuExchange(this->bIsDead_, true))
{ {
return; return;
} }
if (this->uAddress) if (this->uAddress_)
{ {
if (this->pSharedSectionHint) if (this->pSharedSectionHint)
{ {
AuStaticCast<ProcessSectionViewReserved>(this->pSharedSectionHint)->Release(this->uAddress); AuStaticCast<ProcessSectionViewReserved>(this->pSharedSectionHint)->Release(this->uAddress_);
} }
if (this->bShouldUnmap_) 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}; int fd {-1};
if ((fd = AuExchange(this->optFd_, -1)) != -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() 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() 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() bool ProcessSectionFileMapView::LockSwap()
{ {
if (!this->uAddress) if (!this->uAddress_)
{ {
return false; return false;
} }
return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength_ } }); return AuMemory::SwapLock::Lock({ { this->uAddress_, this->uLength_ } });
} }
bool ProcessSectionFileMapView::UnlockSwap() bool ProcessSectionFileMapView::UnlockSwap()
{ {
if (!this->uAddress) if (!this->uAddress_)
{ {
return false; 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; void Unmap() override;
bool Flush(AuUInt offset, AuUInt length) override; bool Flush(AuUInt uOffset, AuUInt uLength) override;
AuUInt GetBaseAddress() override; AuUInt GetBaseAddress() override;
AuUInt GetAddress(AuUInt offset) override; AuUInt GetAddress(AuUInt uOffset) override;
AuUInt8 *GetBasePointer() 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 {}; AuSPtr<IProcessSectionView> pSharedSectionHint {};
@ -32,8 +35,10 @@ namespace Aurora::Process
bool UnlockSwap() override; bool UnlockSwap() override;
private: private:
AuUInt uAddress {}; AuUInt uAddress_ {};
AuUInt uLength_ {}; AuUInt uLength_ {};
AuMutex mutex_;
AuAUInt32 uInUse_ {};
bool bShouldUnmap_ {}; bool bShouldUnmap_ {};
int optFd_ {-1}; int optFd_ {-1};
bool bIsDead_ {}; bool bIsDead_ {};