https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b8e091a44c9852fb759e9c...
commit b8e091a44c9852fb759e9cb7f503bab74146a2d1 Author: Thomas Faber thomas.faber@reactos.org AuthorDate: Sat Apr 20 10:48:43 2019 +0200 Commit: Thomas Faber thomas.faber@reactos.org CommitDate: Wed Jul 10 10:58:45 2019 +0200
[NTOS:PNP] Handle arbitrary subkey name lengths in EnumerateDevices. CORE-15882
This also makes it necessary to fix a bug in the previous code: ZwEnumerateKey will not account for space for a null terminator, so to ensure we have space, we must allocate the additional WCHAR, but not include it in the buffer size passed to the function. --- ntoskrnl/io/pnpmgr/pnproot.c | 53 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/io/pnpmgr/pnproot.c b/ntoskrnl/io/pnpmgr/pnproot.c index 34b529ad509..65ea5cc937b 100644 --- a/ntoskrnl/io/pnpmgr/pnproot.c +++ b/ntoskrnl/io/pnpmgr/pnproot.c @@ -450,7 +450,7 @@ EnumerateDevices( HANDLE KeyHandle = NULL; HANDLE SubKeyHandle = NULL; HANDLE DeviceKeyHandle = NULL; - ULONG BufferSize; + ULONG KeyInfoSize, SubKeyInfoSize; ULONG ResultSize; ULONG Index1, Index2; BUFFER Buffer1, Buffer2; @@ -461,15 +461,20 @@ EnumerateDevices( DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
- BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR); - KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT); + KeyInfoSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR); + KeyInfo = ExAllocatePoolWithTag(PagedPool, + KeyInfoSize + sizeof(UNICODE_NULL), + TAG_PNP_ROOT); if (!KeyInfo) { DPRINT("ExAllocatePoolWithTag() failed\n"); Status = STATUS_NO_MEMORY; goto cleanup; } - SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT); + SubKeyInfoSize = KeyInfoSize; + SubKeyInfo = ExAllocatePoolWithTag(PagedPool, + SubKeyInfoSize + sizeof(UNICODE_NULL), + TAG_PNP_ROOT); if (!SubKeyInfo) { DPRINT("ExAllocatePoolWithTag() failed\n"); @@ -496,13 +501,30 @@ EnumerateDevices( Index1, KeyBasicInformation, KeyInfo, - BufferSize, + KeyInfoSize, &ResultSize); if (Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; break; } + else if (Status == STATUS_BUFFER_OVERFLOW || + Status == STATUS_BUFFER_TOO_SMALL) + { + ASSERT(KeyInfoSize < ResultSize); + KeyInfoSize = ResultSize; + ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT); + KeyInfo = ExAllocatePoolWithTag(PagedPool, + KeyInfoSize + sizeof(UNICODE_NULL), + TAG_PNP_ROOT); + if (!KeyInfo) + { + DPRINT1("ExAllocatePoolWithTag(%lu) failed\n", KeyInfoSize); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + continue; + } else if (!NT_SUCCESS(Status)) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); @@ -539,10 +561,29 @@ EnumerateDevices( Index2, KeyBasicInformation, SubKeyInfo, - BufferSize, + SubKeyInfoSize, &ResultSize); if (Status == STATUS_NO_MORE_ENTRIES) + { break; + } + else if (Status == STATUS_BUFFER_OVERFLOW || + Status == STATUS_BUFFER_TOO_SMALL) + { + ASSERT(SubKeyInfoSize < ResultSize); + SubKeyInfoSize = ResultSize; + ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT); + SubKeyInfo = ExAllocatePoolWithTag(PagedPool, + SubKeyInfoSize + sizeof(UNICODE_NULL), + TAG_PNP_ROOT); + if (!SubKeyInfo) + { + DPRINT1("ExAllocatePoolWithTag(%lu) failed\n", SubKeyInfoSize); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + continue; + } else if (!NT_SUCCESS(Status)) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);