[NTOS:IO] IoVolumeDeviceToDosName(): Fix returned DosName buffer initialization (#6990)

The VolumePath buffer returned by IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
contains one string stored as a multi-NUL-terminated string, whose
total length is given by its `MultiSzLength` member.

The DosName UNICODE_STRING just returns the (single) string as a normal
NUL-terminated string. So, we need to remove the two NUL-terminators
from the `MultiSzLength` count to retrieve the correct length.
This commit is contained in:
Hermès Bélusca-Maïto 2024-06-04 17:21:03 +02:00
parent f315111bb5
commit 0e01cbc6cd
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -1367,7 +1367,7 @@ IoVolumeDeviceToDosName(
* Even if MOUNTMGR_VOLUME_PATHS allows bigger name lengths * Even if MOUNTMGR_VOLUME_PATHS allows bigger name lengths
* than MAXUSHORT, we can't use them, because we have to return * than MAXUSHORT, we can't use them, because we have to return
* this in an UNICODE_STRING that stores length in a USHORT. */ * this in an UNICODE_STRING that stores length in a USHORT. */
Length = sizeof(VolumePath) + VolumePath.MultiSzLength; Length = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + VolumePath.MultiSzLength;
if (Length > MAXUSHORT) if (Length > MAXUSHORT)
{ {
Status = STATUS_INVALID_BUFFER_SIZE; Status = STATUS_INVALID_BUFFER_SIZE;
@ -1407,13 +1407,14 @@ IoVolumeDeviceToDosName(
goto ReleaseMemory; goto ReleaseMemory;
} }
/* Set output string */ /* Set the output string. Discount the last two
DosName->Length = (USHORT)VolumePathPtr->MultiSzLength; * NUL-terminators from the multi-string length. */
DosName->MaximumLength = (USHORT)VolumePathPtr->MultiSzLength + sizeof(UNICODE_NULL); DosName->Length = (USHORT)VolumePathPtr->MultiSzLength - 2 * sizeof(UNICODE_NULL);
/* Our MOUNTMGR_VOLUME_PATHS will be used as output buffer */ DosName->MaximumLength = DosName->Length + sizeof(UNICODE_NULL);
/* Recycle our MOUNTMGR_VOLUME_PATHS as the output buffer
* and move the NUL-terminated string to the beginning */
DosName->Buffer = (PWSTR)VolumePathPtr; DosName->Buffer = (PWSTR)VolumePathPtr;
/* Move name at the begin, RtlMoveMemory is OK with overlapping */ RtlMoveMemory(DosName->Buffer, VolumePathPtr->MultiSz, DosName->Length);
RtlMoveMemory(DosName->Buffer, VolumePathPtr->MultiSz, VolumePathPtr->MultiSzLength);
DosName->Buffer[DosName->Length / sizeof(WCHAR)] = UNICODE_NULL; DosName->Buffer[DosName->Length / sizeof(WCHAR)] = UNICODE_NULL;
/* Don't release the buffer, just dereference the FO and return success */ /* Don't release the buffer, just dereference the FO and return success */