PreviousMode

Когда приложение в пользовательском режиме вызывает версию Nt или Zw собственной подпрограммы системных служб, механизм системного вызова перехватывает вызывающий поток в режим ядра. Чтобы указать, что значения параметров были получены в пользовательском режиме, обработчик ловушки для системного вызова задает для поля PreviousMode в объекте потока вызывающего объекта значение UserMode. Подпрограмма собственных системных служб проверяет поле PreviousMode вызывающего потока, чтобы определить, относятся ли параметры к источнику пользовательского режима.

Если драйвер в режиме ядра вызывает собственную подпрограмму системных служб и передает в подпрограмму значения параметров из источника режима ядра, драйвер должен убедиться, что для поля PreviousMode в текущем объекте потока задано значение KernelMode.

Драйвер режима ядра может выполняться в контексте произвольного потока, а для поля PreviousMode этого потока может быть задано значение UserMode. В этом случае драйвер режима ядра может вызвать версию Zw собственной подпрограммы системных служб, чтобы сообщить подпрограмме, что значения параметров относятся к доверенному источнику в режиме ядра. Вызов Zw переходит к функции тонкой оболочки, которая переопределяет значение PreviousMode в текущем объекте потока. Функция-оболочка присваивает свойству PreviousMode значение KernelMode и вызывает nt-версию подпрограммы. При возвращении из nt-версии подпрограммы функция-оболочка восстанавливает исходное значение PreviousMode объекта потока и возвращает .

Драйвер в режиме ядра может напрямую вызывать nt-версию собственной подпрограммы системных служб. Когда драйвер в режиме ядра обрабатывает запрос ввода-вывода, который может возникнуть либо в пользовательском режиме, либо в режиме ядра, драйвер может вызвать nt-версию подпрограммы, чтобы значение PreviousMode текущего потока оставалось неизменным во время вызова. Подпрограмма NtXxx проверяет значение PreviousMode вызывающего потока, чтобы определить, относятся ли значения параметров к приложению пользовательского режима или компоненту режима ядра, и обрабатывает их соответствующим образом.

Ошибка может возникнуть, если драйвер в режиме ядра вызывает подпрограмму NtXxx , а значение PreviousMode в текущем объекте потока не точно указывает, являются ли значения параметров из пользовательского режима или источника в режиме ядра.

Например, предположим, что драйвер в режиме ядра работает в контексте произвольного потока, а значение PreviousMode для этого потока равно UserMode. Если драйвер передает дескриптор файла в режиме ядра подпрограмме NtClose , эта подпрограмма проверяет значение PreviousMode и решает, что дескриптор должен быть дескриптором пользовательского режима. Если ntClose не находит дескриптор в таблице дескрипторов пользовательского режима, он возвращает код ошибки STATUS_INVALID_HANDLE. Между тем, драйвер утечки дескриптора режима ядра, который никогда не был закрыт.

Другой пример: если параметры для подпрограммы NtXxx включают входной или выходной буфер, а в случае PreviousMode = UserMode, подпрограмма вызывает подпрограмму ProbeForRead или ProbeForWrite для проверки буфера. Если буфер был выделен в системной памяти, а не в памяти в пользовательском режиме, подпрограмма ProbeForXxx вызывает исключение, а подпрограмма NtXxx возвращает код ошибки STATUS_ACCESS_VIOLATION.

При необходимости драйвер может вызвать подпрограмму ExGetPreviousMode , чтобы получить значение PreviousMode из текущего объекта потока. Или драйвер может считывать поле RequestorMode из структуры IRP , которая описывает запрошенную операцию ввода-вывода. Поле RequestorMode содержит копию значения PreviousMode из потока, который запросил операцию.