mirror of
https://github.com/reactos/reactos.git
synced 2024-08-07 19:58:21 +00:00
[KERNEL32]: Fix multiple issues in BaseCreateStack:
- StackLimit was set incorrectly. - Code was not using BaseStaticServerdata, but querying NT instead. - Fix memory leak in failure case. - StackCommit and StackReserved values were not aligned correctly. - Windows Server 2003+ feature of "Guaranteed Stack Commit Size" was not respected. - Some math was screwy. - Failure to get NT headers was not handled. svn path=/trunk/; revision=54285
This commit is contained in:
parent
e5f31ab0a9
commit
4ba4fdcb2c
|
@ -201,7 +201,7 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the stack for the fiber */
|
/* Create the stack for the fiber */
|
||||||
Status = BasepCreateStack(NtCurrentProcess(),
|
Status = BaseCreateStack(NtCurrentProcess(),
|
||||||
dwStackCommitSize,
|
dwStackCommitSize,
|
||||||
dwStackReserveSize,
|
dwStackReserveSize,
|
||||||
&InitialTeb);
|
&InitialTeb);
|
||||||
|
|
|
@ -187,7 +187,7 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
|
||||||
DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
|
DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
|
||||||
|
|
||||||
/* Create the Thread's Stack */
|
/* Create the Thread's Stack */
|
||||||
BasepCreateStack(ProcessHandle,
|
BaseCreateStack(ProcessHandle,
|
||||||
SectionImageInfo->MaximumStackSize,
|
SectionImageInfo->MaximumStackSize,
|
||||||
SectionImageInfo->CommittedStackSize,
|
SectionImageInfo->CommittedStackSize,
|
||||||
&InitialTeb);
|
&InitialTeb);
|
||||||
|
|
|
@ -137,7 +137,7 @@ CreateRemoteThread(HANDLE hProcess,
|
||||||
ClientId.UniqueProcess = hProcess;
|
ClientId.UniqueProcess = hProcess;
|
||||||
|
|
||||||
/* Create the Stack */
|
/* Create the Stack */
|
||||||
Status = BasepCreateStack(hProcess,
|
Status = BaseCreateStack(hProcess,
|
||||||
dwStackSize,
|
dwStackSize,
|
||||||
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
|
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
|
||||||
dwStackSize : 0,
|
dwStackSize : 0,
|
||||||
|
|
|
@ -247,60 +247,64 @@ BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
WINAPI
|
WINAPI
|
||||||
BasepCreateStack(HANDLE hProcess,
|
BaseCreateStack(HANDLE hProcess,
|
||||||
SIZE_T StackReserve,
|
SIZE_T StackReserve,
|
||||||
SIZE_T StackCommit,
|
SIZE_T StackCommit,
|
||||||
PINITIAL_TEB InitialTeb)
|
PINITIAL_TEB InitialTeb)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
|
||||||
PIMAGE_NT_HEADERS Headers;
|
PIMAGE_NT_HEADERS Headers;
|
||||||
ULONG_PTR Stack = 0;
|
ULONG_PTR Stack;
|
||||||
BOOLEAN UseGuard = FALSE;
|
BOOLEAN UseGuard;
|
||||||
|
ULONG PageSize, Dummy, AllocationGranularity;
|
||||||
DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
|
SIZE_T StackReserveHeader, StackCommitHeader, GuardPageSize, GuaranteedStackCommit;
|
||||||
|
DPRINT("BaseCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
|
||||||
hProcess, StackReserve, StackCommit);
|
hProcess, StackReserve, StackCommit);
|
||||||
|
|
||||||
/* Get some memory information */
|
/* Read page size */
|
||||||
Status = NtQuerySystemInformation(SystemBasicInformation,
|
PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||||
&SystemBasicInfo,
|
AllocationGranularity = BaseStaticServerData->SysInfo.AllocationGranularity;
|
||||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
|
||||||
NULL);
|
/* Get the Image Headers */
|
||||||
if (!NT_SUCCESS(Status))
|
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||||
|
if (!Headers) return STATUS_INVALID_IMAGE_FORMAT;
|
||||||
|
|
||||||
|
StackCommitHeader = Headers->OptionalHeader.SizeOfStackCommit;
|
||||||
|
StackReserveHeader = Headers->OptionalHeader.SizeOfStackReserve;
|
||||||
|
|
||||||
|
if (!StackReserve) StackReserve = StackReserveHeader;
|
||||||
|
|
||||||
|
if (!StackCommit)
|
||||||
{
|
{
|
||||||
DPRINT1("Failure to query system info\n");
|
StackCommit = StackCommitHeader;
|
||||||
return Status;
|
}
|
||||||
|
else if (StackCommit >= StackReserve)
|
||||||
|
{
|
||||||
|
StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackCommit = ROUND_UP(StackCommit, PageSize);
|
||||||
|
StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
|
||||||
|
|
||||||
|
GuaranteedStackCommit = NtCurrentTeb()->GuaranteedStackBytes;
|
||||||
|
if ((GuaranteedStackCommit) && (StackCommit < GuaranteedStackCommit))
|
||||||
|
{
|
||||||
|
StackCommit = GuaranteedStackCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the Image Settings if we are dealing with the current Process */
|
if (StackCommit >= StackReserve)
|
||||||
if (hProcess == NtCurrentProcess())
|
|
||||||
{
|
{
|
||||||
/* Get the Image Headers */
|
StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
|
||||||
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
|
||||||
|
|
||||||
/* If we didn't get the parameters, find them ourselves */
|
|
||||||
StackReserve = (StackReserve) ?
|
|
||||||
StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
|
|
||||||
StackCommit = (StackCommit) ?
|
|
||||||
StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Use the System Settings if needed */
|
|
||||||
StackReserve = (StackReserve) ? StackReserve :
|
|
||||||
SystemBasicInfo.AllocationGranularity;
|
|
||||||
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Align everything to Page Size */
|
StackCommit = ROUND_UP(StackCommit, PageSize);
|
||||||
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
|
StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
|
||||||
StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
|
|
||||||
#if 1 // FIXME: Remove once Guard Page support is here
|
/* ROS Hack until we support guard page stack expansion */
|
||||||
StackCommit = StackReserve;
|
StackCommit = StackReserve;
|
||||||
#endif
|
|
||||||
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
|
|
||||||
|
|
||||||
/* Reserve memory for the stack */
|
/* Reserve memory for the stack */
|
||||||
|
Stack = 0;
|
||||||
Status = ZwAllocateVirtualMemory(hProcess,
|
Status = ZwAllocateVirtualMemory(hProcess,
|
||||||
(PVOID*)&Stack,
|
(PVOID*)&Stack,
|
||||||
0,
|
0,
|
||||||
|
@ -309,7 +313,7 @@ BasepCreateStack(HANDLE hProcess,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failure to reserve stack\n");
|
DPRINT1("Failure to reserve stack: %lx\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,11 +329,15 @@ BasepCreateStack(HANDLE hProcess,
|
||||||
/* Check if we will need a guard page */
|
/* Check if we will need a guard page */
|
||||||
if (StackReserve > StackCommit)
|
if (StackReserve > StackCommit)
|
||||||
{
|
{
|
||||||
Stack -= SystemBasicInfo.PageSize;
|
Stack -= PageSize;
|
||||||
StackCommit += SystemBasicInfo.PageSize;
|
StackCommit += PageSize;
|
||||||
UseGuard = TRUE;
|
UseGuard = TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UseGuard = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate memory for the stack */
|
/* Allocate memory for the stack */
|
||||||
Status = ZwAllocateVirtualMemory(hProcess,
|
Status = ZwAllocateVirtualMemory(hProcess,
|
||||||
(PVOID*)&Stack,
|
(PVOID*)&Stack,
|
||||||
|
@ -340,6 +348,8 @@ BasepCreateStack(HANDLE hProcess,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failure to allocate stack\n");
|
DPRINT1("Failure to allocate stack\n");
|
||||||
|
GuardPageSize = 0;
|
||||||
|
ZwFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,10 +359,8 @@ BasepCreateStack(HANDLE hProcess,
|
||||||
/* Create a guard page */
|
/* Create a guard page */
|
||||||
if (UseGuard)
|
if (UseGuard)
|
||||||
{
|
{
|
||||||
SIZE_T GuardPageSize = SystemBasicInfo.PageSize;
|
/* Set the guard page */
|
||||||
ULONG Dummy;
|
GuardPageSize = PAGE_SIZE;
|
||||||
|
|
||||||
/* Attempt maximum space possible */
|
|
||||||
Status = ZwProtectVirtualMemory(hProcess,
|
Status = ZwProtectVirtualMemory(hProcess,
|
||||||
(PVOID*)&Stack,
|
(PVOID*)&Stack,
|
||||||
&GuardPageSize,
|
&GuardPageSize,
|
||||||
|
@ -360,12 +368,13 @@ BasepCreateStack(HANDLE hProcess,
|
||||||
&Dummy);
|
&Dummy);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failure to create guard page\n");
|
DPRINT1("Failure to set guard page\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the Stack Limit keeping in mind the Guard Page */
|
/* Update the Stack Limit keeping in mind the Guard Page */
|
||||||
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize);
|
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
|
||||||
|
GuardPageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are done! */
|
/* We are done! */
|
||||||
|
|
|
@ -173,7 +173,7 @@ BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
WINAPI
|
WINAPI
|
||||||
BasepCreateStack(HANDLE hProcess,
|
BaseCreateStack(HANDLE hProcess,
|
||||||
SIZE_T StackReserve,
|
SIZE_T StackReserve,
|
||||||
SIZE_T StackCommit,
|
SIZE_T StackCommit,
|
||||||
PINITIAL_TEB InitialTeb);
|
PINITIAL_TEB InitialTeb);
|
||||||
|
|
Loading…
Reference in a new issue