Сбой при проверке размера буферов
При обработке ioCTL и FSCTL, реализующих буферизированные операции ввода-вывода, драйвер всегда должен проверка размеры входных и выходных буферов, чтобы убедиться, что буферы могут содержать все запрошенные данные. Если в запросе указано FILE_ANY_ACCESS, как и большинство ICTL драйвера и FSCTL, любой вызывающий объект, имеющий дескриптор устройства, имеет доступ к буферизованному запросу IOCTL или FSCTL для этого устройства и может считывать или записывать данные за пределами буфера.
Размер входного буфера
Например, предположим, что следующий код отображается в подпрограмме, вызываемой из подпрограммы Dispatch , и что драйвер не проверил размеры буфера, переданные в IRP:
switch (ControlCode)
...
...
case IOCTL_NEW_ADDRESS:{
tNEW_ADDRESS *pNewAddress =
pIrp->AssociatedIrp.SystemBuffer;
pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);
В примере не проверка размеры буфера перед инструкцией присваивания (выделено). В результате ссылка pNewAddress-Address> в следующей строке может привести к сбою, если входной буфер недостаточно велик для tNEW_ADDRESS структуры.
Следующий код проверяет размеры буфера, чтобы избежать потенциальных проблем:
case IOCTL_NEW_ADDRESS: {
tNEW_ADDRESS *pNewAddress =
pIrp->AssociatedIrp.SystemBuffer;
if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(tNEW_ADDRESS)) {
pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);
Код для обработки других буферизированных операций ввода-вывода, например запросов WMI, использующих буферы переменной величины, может иметь аналогичные ошибки.
Размер выходного буфера
Проблемы выходного буфера аналогичны проблемам входного буфера. Они могут легко повредить пул, а вызывающие пользователи пользовательского режима могут не знать, что произошла какая-либо ошибка.
В следующем примере драйверу не удается проверка размер SystemBuffer:
case IOCTL_GET_INFO: {
Info = Irp->AssociatedIrp.SystemBuffer;
Info->NumIF = NumIF;
...
...
Irp->IoStatus.Information =
NumIF*sizeof(GET_INFO_ITEM)+sizeof(ULONG);
Irp->IoStatus.Status = ntStatus;
}
Если предположить, что поле NumIF системного буфера указывает количество входных элементов, в этом примере можно задать ioStatus.Information значение больше, чем выходной буфер, и таким образом вернуть слишком много информации в код пользовательского режима. Если приложение закодировано неправильно и вызывает с слишком небольшим выходным буфером, предыдущий код может повредить пул, записав за пределы системного буфера.
Помните, что диспетчер ввода-вывода предполагает, что значение в поле Сведения является допустимым. Если вызывающий объект передает допустимый адрес в режиме ядра для выходного буфера и размер нулевых байтов, могут возникнуть серьезные проблемы, если драйвер не проверка размер выходного буфера и таким образом найти ошибку.