Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Любой драйвер, независимо от того, поддерживает ли он IRPs или быстрые операции ввода-вывода, должен проверять любой адрес в пространстве пользователя, прежде чем пытаться использовать его. Диспетчер ввода-вывода не проверяет такие адреса и не проверяет указатели, внедренные в буферы, передаваемые драйверам.
Сбой проверки адресов, передаваемых в METHOD_NEITHER ioCTLs и FSCTLs
Диспетчер операций ввода-вывода не выполняет никаких проверок для METHOD_NEITHER ioCTLs и FSCTLs. Чтобы убедиться, что адреса пространства пользователя допустимы, драйвер должен использовать подпрограммы ProbeForRead и ProbeForWrite, заключив все ссылки на буферы в блоки try/except.
В следующем примере драйвер предполагает, что значение, переданное в Type3InputBuffer , представляет допустимый адрес.
case IOCTL_GET_HANDLER:
{
PULONG EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
*EntryPoint = (ULONG)DriverEntryPoint;
...
}
Следующий код избегает этой проблемы:
case IOCTL_GET_HANDLER:
{
PULONG_PTR EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
try
{
if (Irp->RequestorMode != KernelMode)
{
ProbeForWrite(EntryPoint,
sizeof(ULONG_PTR),
TYPE_ALIGNMENT(ULONG_PTR));
}
*EntryPoint = (ULONG_PTR)DriverEntryPoint;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
...
}
...
}
Обратите внимание, что правильный код приводит DriverEntryPoint к ULONG_PTR вместо ULONG. Это изменение позволяет использовать в 64-разрядной среде Windows.
Сбой проверки указателей, внедренных в буферные запросы ввода-вывода
Часто драйверы внедряют указатели в буферные запросы, как показано в следующем примере:
struct ret_buf
{
void *arg; // Pointer embedded in request
int rval;
};
pBuf = Irp->AssociatedIrp.SystemBuffer;
...
arg = pBuf->arg; // Fetch the embedded pointer
...
// If the arg pointer is not valid, the following
// statement can corrupt the system:
RtlMoveMemory(arg, &info, sizeof(info));
В этом примере драйвер должен проверить внедренный указатель с помощью подпрограмм ProbeXxx, заключенных в блок try/except так же, как и для методологии METHOD_NEITHER IOCTLs, описанных ранее. Хотя внедрение указателя позволяет драйверу возвращать дополнительные сведения, драйвер может более эффективно достичь того же результата с помощью относительного смещения или буфера переменной длины.
Дополнительные сведения об использовании блоков try/except для обработки недопустимых адресов см. в разделе "Обработка исключений".