Author: fireball Date: Tue Dec 20 18:16:14 2011 New Revision: 54711
URL: http://svn.reactos.org/svn/reactos?rev=54711&view=rev Log: [NTOS] - A number of fixes to CmpQueryKeyName(): * Properly check the provided buffer size against needed size. * Don't overwrite user provided buffer. * Write as much data as could fit into the buffer (this is normal behaviour for any query function in the kernel), returning STATUS_INFO_LENGTH_MISMATCH if not all data were written.
Thanks to r3ddr4g0n for identifying the problem, testing with DPH and testing this patch.
Modified: trunk/reactos/ntoskrnl/config/cmsysini.c
Modified: trunk/reactos/ntoskrnl/config/cmsysini.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmsysini.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmsysini.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/config/cmsysini.c [iso-8859-1] Tue Dec 20 18:16:14 2011 @@ -121,6 +121,7 @@ IN KPROCESSOR_MODE PreviousMode) { PUNICODE_STRING KeyName; + ULONG BytesToCopy; NTSTATUS Status = STATUS_SUCCESS; PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)ObjectBody; PCM_KEY_CONTROL_BLOCK Kcb = KeyBody->KeyControlBlock; @@ -155,16 +156,32 @@ /* Set the returned length */ *ReturnLength = KeyName->Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR);
- /* Check if it fits into the provided buffer */ - if ((Length < sizeof(OBJECT_NAME_INFORMATION)) || - (Length < (*ReturnLength - sizeof(OBJECT_NAME_INFORMATION)))) + /* Calculate amount of bytes to copy into the buffer */ + BytesToCopy = KeyName->Length + sizeof(WCHAR); + + /* Check if the provided buffer is too small to fit even anything */ + if ((Length <= sizeof(OBJECT_NAME_INFORMATION)) || + ((Length < (*ReturnLength)) && (BytesToCopy < sizeof(WCHAR)))) { /* Free the buffer allocated by CmpConstructName */ ExFreePool(KeyName);
- /* Return buffer length failure */ + /* Return buffer length failure without writing anything there because nothing fits */ return STATUS_INFO_LENGTH_MISMATCH; } + + /* Check if the provided buffer can be partially written */ + if (Length < (*ReturnLength)) + { + /* Yes, indicate so in the return status */ + Status = STATUS_INFO_LENGTH_MISMATCH; + + /* Calculate amount of bytes which the provided buffer could handle */ + BytesToCopy = Length - sizeof(OBJECT_NAME_INFORMATION); + } + + /* Remove the null termination character from the size */ + BytesToCopy -= sizeof(WCHAR);
/* Fill in the result */ _SEH2_TRY @@ -177,7 +194,10 @@ /* Copy string content*/ RtlCopyMemory(ObjectNameInfo->Name.Buffer, KeyName->Buffer, - *ReturnLength); + BytesToCopy); + + /* Null terminate it */ + ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = 0; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {