Refactor process quota return logic and fix atomic exchange operations
This commit is contained in:
@@ -54,10 +54,13 @@ PS::Quota::DereferenceQuotaBlock(IN PEPROCESS_QUOTA_BLOCK QuotaBlock)
|
|||||||
MM::Quota::ReturnPoolQuota((MMPOOL_TYPE)Index, ReturnAmount);
|
MM::Quota::ReturnPoolQuota((MMPOOL_TYPE)Index, ReturnAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Unlink the quota block from the global tracking list */
|
/* Acquire a quota lock */
|
||||||
RTL::LinkedList::RemoveEntryList(&QuotaBlock->QuotaList);
|
KE::SpinLockGuard SpinLock(&QuotaLock);
|
||||||
|
|
||||||
|
/* Unlink the quota block from the global tracking list */
|
||||||
|
RTL::LinkedList::RemoveEntryList(&QuotaBlock->QuotaList);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the physical memory */
|
/* Free the physical memory */
|
||||||
MM::Allocator::FreePool(QuotaBlock, TAG_PS_QUOTA_BLOCK);
|
MM::Allocator::FreePool(QuotaBlock, TAG_PS_QUOTA_BLOCK);
|
||||||
@@ -98,15 +101,24 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
|
|||||||
QuotaEntry = &QuotaBlock->QuotaEntry[QuotaType];
|
QuotaEntry = &QuotaBlock->QuotaEntry[QuotaType];
|
||||||
CurrentUsage = QuotaEntry->Usage;
|
CurrentUsage = QuotaEntry->Usage;
|
||||||
|
|
||||||
/* Ensure quota usage does not exceed the limit */
|
/* Check if process provided */
|
||||||
if((Process != NULLPTR && Process->QuotaUsage[QuotaType] < Amount) || (CurrentUsage < Amount))
|
if(Process != NULLPTR)
|
||||||
{
|
{
|
||||||
/* Quota underflow detected, raise kernel panic */
|
/* Check if this is the system process */
|
||||||
KE::Crash::Panic(0x21,
|
if(Process == PS::Process::GetSystemProcess())
|
||||||
(ULONG_PTR)Process,
|
{
|
||||||
(ULONG_PTR)QuotaType,
|
/* Do not do anything for system processes, return */
|
||||||
Process ? (ULONG_PTR)Process->QuotaUsage[QuotaType] : (ULONG_PTR)CurrentUsage,
|
return;
|
||||||
(ULONG_PTR)Amount);
|
}
|
||||||
|
else if(Process->QuotaUsage[QuotaType] < Amount || CurrentUsage < Amount)
|
||||||
|
{
|
||||||
|
/* Quota underflow detected, raise kernel panic */
|
||||||
|
KE::Crash::Panic(0x21,
|
||||||
|
(ULONG_PTR)Process,
|
||||||
|
(ULONG_PTR)QuotaType,
|
||||||
|
Process ? (ULONG_PTR)Process->QuotaUsage[QuotaType] : (ULONG_PTR)CurrentUsage,
|
||||||
|
(ULONG_PTR)Amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the thresholds for returning excess quota limit */
|
/* Determine the thresholds for returning excess quota limit */
|
||||||
@@ -126,8 +138,8 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
|
|||||||
|
|
||||||
/* Attempt a lock-free update to shrink the quota limit */
|
/* Attempt a lock-free update to shrink the quota limit */
|
||||||
NewLimit = CurrentLimit - GiveBackAmount;
|
NewLimit = CurrentLimit - GiveBackAmount;
|
||||||
ExpectedLimit = (SIZE_T)RTL::Atomic::CompareExchangePointer((PVOID*)&QuotaEntry->Limit, (PVOID)NewLimit,
|
ExpectedLimit = (SIZE_T)RTL::Atomic::CompareExchange64((PLONG_PTR)&QuotaEntry->Limit, (LONG_PTR)NewLimit,
|
||||||
(PVOID)CurrentLimit);
|
(LONG_PTR)CurrentLimit);
|
||||||
|
|
||||||
/* Check if the atomic limit update succeeded */
|
/* Check if the atomic limit update succeeded */
|
||||||
if(ExpectedLimit == CurrentLimit)
|
if(ExpectedLimit == CurrentLimit)
|
||||||
@@ -139,7 +151,7 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
|
|||||||
if(AccumulatedGiveBack > GiveBackLimit)
|
if(AccumulatedGiveBack > GiveBackLimit)
|
||||||
{
|
{
|
||||||
/* Extract the accumulated return amount and reset the counter to zero */
|
/* Extract the accumulated return amount and reset the counter to zero */
|
||||||
ExtractedReturnAmount = (SIZE_T)RTL::Atomic::ExchangePointer((PVOID*)&QuotaEntry->Return, (PVOID)0);
|
ExtractedReturnAmount = (SIZE_T)RTL::Atomic::Exchange64((PLONG_PTR)&QuotaEntry->Return, (LONG_PTR)0);
|
||||||
|
|
||||||
/* Check if there is anything to return */
|
/* Check if there is anything to return */
|
||||||
if(ExtractedReturnAmount > 0)
|
if(ExtractedReturnAmount > 0)
|
||||||
@@ -156,7 +168,7 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
|
|||||||
RTL::Atomic::Add64((PLONG_PTR)&QuotaEntry->Usage, (SIZE_T)(-(SSIZE_T)Amount));
|
RTL::Atomic::Add64((PLONG_PTR)&QuotaEntry->Usage, (SIZE_T)(-(SSIZE_T)Amount));
|
||||||
|
|
||||||
/* Check if a specific process was provided */
|
/* Check if a specific process was provided */
|
||||||
if(Process != NULLPTR)
|
if(Process)
|
||||||
{
|
{
|
||||||
/* Decrease the process's specific usage count */
|
/* Decrease the process's specific usage count */
|
||||||
RTL::Atomic::Add64((PLONG_PTR)&Process->QuotaUsage[QuotaType], (SIZE_T)(-(SSIZE_T)Amount));
|
RTL::Atomic::Add64((PLONG_PTR)&Process->QuotaUsage[QuotaType], (SIZE_T)(-(SSIZE_T)Amount));
|
||||||
@@ -186,7 +198,7 @@ PS::Quota::ReturnSharedPoolQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
|
|||||||
IN SIZE_T NonPagedAmount)
|
IN SIZE_T NonPagedAmount)
|
||||||
{
|
{
|
||||||
/* Check for NULL pointers and bypass markers */
|
/* Check for NULL pointers and bypass markers */
|
||||||
if(QuotaBlock == NULLPTR || QuotaBlock == (PEPROCESS_QUOTA_BLOCK)1)
|
if(!QuotaBlock || QuotaBlock == PS_QUOTA_BYPASS_MARKER)
|
||||||
{
|
{
|
||||||
/* No quota tracking is required for the system process or empty blocks, return */
|
/* No quota tracking is required for the system process or empty blocks, return */
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user