Skip to content

Free unused trampoline regions on abort and attach error #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Source/SlimDetours/SlimDetours.inl
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ detour_free_trampoline(

VOID detour_free_unused_trampoline_regions(VOID);

VOID
detour_free_trampoline_region_if_unused(
_In_ PDETOUR_TRAMPOLINE pTrampoline);

BYTE
detour_align_from_trampoline(
_In_ PDETOUR_TRAMPOLINE pTrampoline,
Expand Down
47 changes: 39 additions & 8 deletions Source/SlimDetours/Trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,24 +400,29 @@ detour_is_region_empty(
return TRUE;
}

static
VOID
detour_free_unused_trampoline_regions(VOID)
detour_free_region(
_In_ PDETOUR_REGION* ppRegionBase,
_In_ PDETOUR_REGION pRegion)
{
PVOID pMem;
SIZE_T sMem;
*ppRegionBase = pRegion->pNext;
PVOID pMem = pRegion;
SIZE_T sMem = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &pMem, &sMem, MEM_RELEASE);
}

VOID
detour_free_unused_trampoline_regions(VOID)
{
PDETOUR_REGION* ppRegionBase = &s_pRegions;
PDETOUR_REGION pRegion = s_pRegions;

while (pRegion != NULL)
{
if (detour_is_region_empty(pRegion))
{
*ppRegionBase = pRegion->pNext;

pMem = pRegion;
sMem = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &pMem, &sMem, MEM_RELEASE);
detour_free_region(ppRegionBase, pRegion);
s_pRegion = NULL;
} else
{
Expand All @@ -427,6 +432,32 @@ detour_free_unused_trampoline_regions(VOID)
}
}

VOID
detour_free_trampoline_region_if_unused(
_In_ PDETOUR_TRAMPOLINE pTrampoline)
{
PDETOUR_REGION pTargetRegion = (PDETOUR_REGION)((ULONG_PTR)pTrampoline & ~(ULONG_PTR)0xffff);

PDETOUR_REGION* ppRegionBase = &s_pRegions;
PDETOUR_REGION pRegion = s_pRegions;

while (pRegion != NULL)
{
if (pRegion == pTargetRegion)
{
if (detour_is_region_empty(pRegion))
{
detour_free_region(ppRegionBase, pRegion);
s_pRegion = NULL;
}
break;
}

ppRegionBase = &pRegion->pNext;
pRegion = *ppRegionBase;
}
}

BYTE
detour_align_from_trampoline(
_In_ PDETOUR_TRAMPOLINE pTrampoline,
Expand Down
7 changes: 7 additions & 0 deletions Source/SlimDetours/Transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ SlimDetoursTransactionAbort(VOID)
PVOID pMem;
SIZE_T sMem;
DWORD dwOld;
BOOL freed = FALSE;

if (s_nPendingThreadId != NtCurrentThreadId())
{
Expand All @@ -115,13 +116,18 @@ SlimDetoursTransactionAbort(VOID)
{
detour_free_trampoline(o->pTrampoline);
o->pTrampoline = NULL;
freed = TRUE;
}

PDETOUR_OPERATION n = o->pNext;
detour_memory_free(o);
o = n;
}
s_pPendingOperations = NULL;
if (freed)
{
detour_free_unused_trampoline_regions();
}

// Make sure the trampoline pages are no longer writable.
detour_runnable_trampoline_regions();
Expand Down Expand Up @@ -324,6 +330,7 @@ SlimDetoursAttach(
if (pTrampoline != NULL)
{
detour_free_trampoline(pTrampoline);
detour_free_trampoline_region_if_unused(pTrampoline);
pTrampoline = NULL;
}
if (o != NULL)
Expand Down