Author: pschweitzer
Date: Tue Sep 10 13:42:34 2013
New Revision: 60003
URL: http://svn.reactos.org/svn/reactos?rev=60003&view=rev
Log:
[NTOSKRNL]
Fix string size to store GPT GUIDs.
This was causing a buffer overflow (with ending null char) and thus a stack corruption.
The side effect of the stack corruption was that the debug code (display) was looping
forever while attempting to read partition table making ntoskrnl unable to boot with
a machine where there's a GPT disk.
Kernel is now able again to handle GPT disks (and they can be used again in user-land).
This was magically hidding before r59923 or by disabling NDEBUG. Lovely Heisenbugs :-).
Modified:
trunk/reactos/ntoskrnl/fstub/fstubex.c
Modified: trunk/reactos/ntoskrnl/fstub/fstubex.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fstub/fstubex.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/fstub/fstubex.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fstub/fstubex.c [iso-8859-1] Tue Sep 10 13:42:34 2013
@@ -86,6 +86,8 @@
#define EFI_HEADER_REVISION_1 0x00010000
/* Defines system type for MBR showing that a GPT is following */
#define EFI_PMBR_OSTYPE_EFI 0xEE
+/* Defines size to store a complete GUID + null char */
+#define EFI_GUID_STRING_SIZE 0x27
#define IS_VALID_DISK_INFO(Disk) \
(Disk) && \
@@ -534,7 +536,7 @@
FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
{
ULONG i;
- CHAR Guid[38];
+ CHAR Guid[EFI_GUID_STRING_SIZE];
PAGED_CODE();
DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
@@ -575,7 +577,7 @@
FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
IN ULONG PartitionNumber)
{
- CHAR Guid[38];
+ CHAR Guid[EFI_GUID_STRING_SIZE];
PAGED_CODE();
DPRINT("Printing partition %lu\n", PartitionNumber);
@@ -614,7 +616,7 @@
FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
IN ULONG PartitionNumber)
{
- CHAR Guid[38];
+ CHAR Guid[EFI_GUID_STRING_SIZE];
PAGED_CODE();
DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
Author: ion
Date: Tue Sep 10 10:02:27 2013
New Revision: 60002
URL: http://svn.reactos.org/svn/reactos?rev=60002&view=rev
Log:
[NTOSKRNL]: Implement ExAllocatePoolWithQuotaTag. However PsChargeProcessPoolQuota is still unimplemented so nothing really gets charged (we do write the owner process, though).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/expool.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/expool.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] Tue Sep 10 10:02:27 2013
@@ -2511,11 +2511,114 @@
IN SIZE_T NumberOfBytes,
IN ULONG Tag)
{
- //
- // Allocate the pool
- //
- UNIMPLEMENTED;
- return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
+ BOOLEAN Raise = TRUE;
+ PVOID Buffer;
+ PPOOL_HEADER Entry;
+ NTSTATUS Status;
+ PEPROCESS Process = PsGetCurrentProcess();
+
+ //
+ // Check if we should fail intead of raising an exception
+ //
+ if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE)
+ {
+ Raise = FALSE;
+ PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE;
+ }
+
+ //
+ // Inject the pool quota mask
+ //
+ PoolType += QUOTA_POOL_MASK;
+
+ //
+ // Check if we have enough space to add the quota owner process, as long as
+ // this isn't the system process, which never gets charged quota
+ //
+ ASSERT(NumberOfBytes != 0);
+ if ((NumberOfBytes <= (PAGE_SIZE - sizeof(POOL_BLOCK_SIZE) - sizeof(PVOID))) &&
+ (Process != PsInitialSystemProcess))
+ {
+ //
+ // Add space for our EPROCESS pointer
+ //
+ NumberOfBytes += sizeof(PEPROCESS);
+ }
+ else
+ {
+ //
+ // We won't be able to store the pointer, so don't use quota for this
+ //
+ PoolType -= QUOTA_POOL_MASK;
+ }
+
+ //
+ // Allocate the pool buffer now
+ //
+ Buffer = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
+
+ //
+ // If the buffer is page-aligned, this is a large page allocation and we
+ // won't touch it
+ //
+ if (PAGE_ALIGN(Buffer) != Buffer)
+ {
+ //
+ // Also if special pool is enabled, and this was allocated from there,
+ // we won't touch it either
+ //
+ if ((ExpPoolFlags & POOL_FLAG_SPECIAL_POOL) &&
+ (MmIsSpecialPoolAddress(Buffer)))
+ {
+ return Buffer;
+ }
+
+ //
+ // If it wasn't actually allocated with quota charges, ignore it too
+ //
+ if (!(PoolType & QUOTA_POOL_MASK)) return Buffer;
+
+ //
+ // If this is the system process, we don't charge quota, so ignore
+ //
+ if (Process == PsInitialSystemProcess) return Buffer;
+
+ //
+ // Actually go and charge quota for the process now
+ //
+ Entry = POOL_ENTRY(Buffer);
+ Status = PsChargeProcessPoolQuota(Process,
+ PoolType & BASE_POOL_TYPE_MASK,
+ Entry->BlockSize * sizeof(POOL_BLOCK_SIZE));
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // Quota failed, back out the allocation, clear the owner, and fail
+ //
+ *(PVOID*)((ULONG_PTR)POOL_NEXT_BLOCK(Entry) - sizeof(PVOID)) = NULL;
+ ExFreePoolWithTag(Buffer, Tag);
+ if (Raise) RtlRaiseStatus(Status);
+ return NULL;
+ }
+
+ //
+ // Quota worked, write the owner and then reference it before returning
+ //
+ *(PVOID*)((ULONG_PTR)POOL_NEXT_BLOCK(Entry) - sizeof(PVOID)) = Process;
+ ObReferenceObject(Process);
+ }
+ else if (!(Buffer) && (Raise))
+ {
+ //
+ // The allocation failed, raise an error if we are in raise mode
+ //
+ RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Return the allocated buffer
+ //
+ return Buffer;
}
#if DBG && KDBG