Pull to refresh

Маленькая, но очень коварная засада с программированием в kernelspace-е в ОС MS Windows

Reading time 1 min
Views 3.7K
На днях отлаживал драйвер, при использовании которого возникали хаотические и, на первый взгляд, какие-то магические BSoD-ы. Все вызовы функций были правильные, никаких ошибок с нулевыми указателями и прочего распространенного гемороя не наблюдалось. Так и не поняв, что же могло случиться с этим драйвером я попросил более опытного коллегу посмотреть что же не так. Через несколько часов он сказал, что понял в чем причина бага. Результат обескуражил нас обоих.

Оказалось, что причина падений банальна проста: в логике драйвера активно использовался стек, нередко функция использовала 10 — 20 кб памяти на стеке под различного рода буфферы и массивы. MSDN говорит, что стек ядра ограничен тремя страницами памяти (что для 32-х битной архитектуры составляет порядка 12кб), в связи с чем лучше воздержаться от множественных вызовов функций и использования рекурсии.
Ошибка переполнения стека ядра вызывает так называемый Double Fault, т.е. процессор пытается сообщить о переполнении стека и положить структуру, содержащую сведения об этой ошибке на уже переполненный стек, таким образом возникает еще одна ошибка и ядру не остается ничего кроме как «умереть в мучениях» (сведения об этом взяты отсюда).
Также, использую функцию IoGetRemainingStackSize мы поняли, что до нашего фильтр-драйвера доходит только 5 — 6 кб памяти на стеке, а следовательно, если в систему будет загружен не один фильтр-драйвер, а несколько, то вероятность сбоев и BSoD-ов сильно возрастет.
Итак, если в вашем драйвере наблюдаются какие-то странные BSoD-ы, проверьте, может быть это из-за недостатка памяти на стеке, и не повторяйте мои ошибки.
Tags:
Hubs:
+57
Comments 101
Comments Comments 101

Articles