Skip to content

Commit 20efea8

Browse files
authored
[USBSTOR] Fix PdoHandleQueryInstanceId and increase serial number descriptor size to MAXIMUM_USB_STRING_LENGTH (reactos#6413)
Serial number on some USB devices might exceed the number of 100 characters (e.g. 120 characters on "SanDisk Ultra 3.2Gen1" pendrive) and cause buffer overflow, resulting in usbstor.sys crash. - Use pool allocation for instance ID generation. Fixes stack overflow on USB storage devices with large serial number. - Print the LUN number as a hexadecimal, not as a character. - Verify the serial number descriptor before using it. - Increase the max descriptor size for serial number to MAXIMUM_USB_STRING_LENGTH. This fixes serial number string truncation. Based on suggestions by disean and ThFabba. CORE-17625
1 parent 398201d commit 20efea8

File tree

3 files changed

+40
-16
lines changed

3 files changed

+40
-16
lines changed

drivers/usb/usbstor/descriptor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ USBSTOR_GetDescriptors(
118118
if (DeviceExtension->DeviceDescriptor->iSerialNumber)
119119
{
120120
// get serial number
121-
Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber);
121+
Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, MAXIMUM_USB_STRING_LENGTH, DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber);
122122
if (!NT_SUCCESS(Status))
123123
{
124124
FreeItem(DeviceExtension->DeviceDescriptor);

drivers/usb/usbstor/pdo.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -437,37 +437,60 @@ USBSTOR_PdoHandleQueryInstanceId(
437437
{
438438
PPDO_DEVICE_EXTENSION PDODeviceExtension;
439439
PFDO_DEVICE_EXTENSION FDODeviceExtension;
440-
WCHAR Buffer[100];
441-
ULONG Length;
440+
PUSB_STRING_DESCRIPTOR Descriptor;
441+
ULONG CharCount;
442442
LPWSTR InstanceId;
443+
NTSTATUS Status;
443444

444-
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
445-
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
445+
PDODeviceExtension = DeviceObject->DeviceExtension;
446+
FDODeviceExtension = PDODeviceExtension->LowerDeviceObject->DeviceExtension;
446447

447-
// format instance id
448-
if (FDODeviceExtension->SerialNumber)
448+
Descriptor = FDODeviceExtension->SerialNumber;
449+
if (Descriptor && (Descriptor->bLength >= sizeof(USB_COMMON_DESCRIPTOR) + sizeof(WCHAR)))
449450
{
450-
// using serial number from device
451-
swprintf(Buffer, L"%s&%c", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN);
451+
/* Format the serial number descriptor only if supported by the device */
452+
CharCount = (Descriptor->bLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(WCHAR) +
453+
(sizeof("&") - 1) +
454+
(sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
455+
sizeof(ANSI_NULL);
452456
}
453457
else
454458
{
455-
// use instance count and LUN
456-
swprintf(Buffer, L"%04lu&%c", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN);
459+
/* Use the instance count and LUN as a fallback */
460+
CharCount = (sizeof("99999999") - 1) + // Instance Count: 8 chars
461+
(sizeof("&") - 1) +
462+
(sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
463+
sizeof(ANSI_NULL);
457464
}
458465

459-
Length = wcslen(Buffer) + 1;
460-
461-
InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), USB_STOR_TAG);
466+
InstanceId = ExAllocatePoolUninitialized(PagedPool, CharCount * sizeof(WCHAR), USB_STOR_TAG);
462467
if (!InstanceId)
463468
{
464469
Irp->IoStatus.Information = 0;
465470
return STATUS_INSUFFICIENT_RESOURCES;
466471
}
467472

468-
wcscpy(InstanceId, Buffer);
473+
if (Descriptor && (Descriptor->bLength >= sizeof(USB_COMMON_DESCRIPTOR) + sizeof(WCHAR)))
474+
{
475+
Status = RtlStringCchPrintfW(InstanceId,
476+
CharCount,
477+
L"%s&%x",
478+
Descriptor->bString,
479+
PDODeviceExtension->LUN);
480+
}
481+
else
482+
{
483+
Status = RtlStringCchPrintfW(InstanceId,
484+
CharCount,
485+
L"%04lu&%x",
486+
FDODeviceExtension->InstanceCount,
487+
PDODeviceExtension->LUN);
488+
}
489+
490+
/* This should not happen */
491+
ASSERT(NT_SUCCESS(Status));
469492

470-
DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId);
493+
DPRINT("USBSTOR_PdoHandleQueryInstanceId '%S'\n", InstanceId);
471494

472495
Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
473496
return STATUS_SUCCESS;

drivers/usb/usbstor/usbstor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define _USBSTOR_H_
33

44
#include <wdm.h>
5+
#include <ntstrsafe.h>
56
#include <usbdi.h>
67
#include <usbbusif.h>
78
#include <usbdlib.h>

0 commit comments

Comments
 (0)