[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.
This commit is contained in:
Thomas Faber 2019-04-20 10:48:43 +02:00
parent b5423ba70b
commit b8e091a44c
No known key found for this signature in database
GPG Key ID: 076E7C3D44720826

View File

@ -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);