Информация об изменениях

Сообщение Re[2]: Как синхронизировать PFLT_POST_OPERATION_CALLBACK и п от 14.09.2018 6:58

Изменено 14.09.2018 7:01 LimyKurn

Re[2]: Как синхронизировать PFLT_POST_OPERATION_CALLBACK и поток -
Здравствуйте, okman, Вы писали:

O>Здравствуйте, LimyKurn, Вы писали:


LK>>Есть POST_OPERATION_CALLBACK — он из операций и всяких собранных данных (вроде PID процесса) формирует готовые строки и добавляет их в "очередь" на логирование.

LK>>...
LK>>В итоге имеем, что никаких lockов сюда вообще нельзя. И как тогда поступить?

O>POST_OPERATION_CALLBACK в общем случае может вызываться на DISPATCH_LEVEL. Поэтому никаких мьютексов и ожиданий,

O>здесь для синхронизации можно использовать только спинлок (потому что спинлок допустимо использовать на этом IRQL, а
O>другие объекты — нет). Очередь и память под ее объекты, соответственно, тоже должна использовать исключительно
O>NonPagedPool(Nx), иначе нарвемся на IRQL_NOT_LESS_OR_EQUAL. Здесь, кстати, нужна повышенная бдительность.
O>Например, имя файла, получаемое через FltGetFileNameInformation, выделяется из paged-пула, поэтому тупо взять его и
O>запихнуть в такую очередь нельзя, нужно сначала где-нибудь в безопасном месте, например, на pre-create или на
O>post-create (там всегда PASSIVE_LEVEL) сделать копию имени в nonpaged-памяти.

O>Использовать FltDoCompletionProcessingWhenSafe или FLT_PREOP_SYNCHRONIZE здесь тоже не стоит, это только ухудшит

O>производительность системы.

А, кстати, что такое pre-create и post-create, у которых PASSIVE_LEVEL? FltGetFileNameInformation тут тоже используется. Проблем вроде BSODов не наблюдается никак. Однако меня больше интересует другое — раз там PASSIVE_LEVEL, то нельзя ли там синхронизировать? Но важно, чтобы решение поддерживало и IRP_MJ_WRITE.

> POST_OPERATION_CALLBACK в общем случае может вызываться на DISPATCH_LEVEL

А если просто отсечь случаи, когда он на нем вызывается? То можно ли будет использовать мьютексы и сможет ли система логировать все операции с файлами, в том числе IRP_MJ_WRITE и операции не только от usermode-приложений, но желательно и от других драйверов?

И что все-таки можно сделать? Я могу согласиться с тем, что решение делать такое жирное логирование в отдельном потоке драйвера — это плохое решение. Но само по себе использование отдельного потока, в который каждые N секунд\минут попадают данные из POST_OPERATION_CALLBACK, вроде бы не относится к такому — это может в некоторых случаях быть нужно. Поэтому хотя бы для общего развития хотелось бы найти решение.

Стоит ли заменить на UNICODE_STRING? В идеале, конечно, хотелось бы нормальный контейнер, как std::vector в C++. На C++ можно писать целый месяц и ни разу ничего не очищать, т.к. ничего и не выделяешь. Сюда бы тоже такое. Кстати, там еще и список один самодельный заменить надо, а то тоже течет. Или быстродействие и другие проблемы помешают реализовать подобное?
Re[2]: Как синхронизировать PFLT_POST_OPERATION_CALLBACK и п
Здравствуйте, okman, Вы писали:

O>Здравствуйте, LimyKurn, Вы писали:


LK>>Есть POST_OPERATION_CALLBACK — он из операций и всяких собранных данных (вроде PID процесса) формирует готовые строки и добавляет их в "очередь" на логирование.

LK>>...
LK>>В итоге имеем, что никаких lockов сюда вообще нельзя. И как тогда поступить?

O>POST_OPERATION_CALLBACK в общем случае может вызываться на DISPATCH_LEVEL. Поэтому никаких мьютексов и ожиданий,

O>здесь для синхронизации можно использовать только спинлок (потому что спинлок допустимо использовать на этом IRQL, а
O>другие объекты — нет). Очередь и память под ее объекты, соответственно, тоже должна использовать исключительно
O>NonPagedPool(Nx), иначе нарвемся на IRQL_NOT_LESS_OR_EQUAL. Здесь, кстати, нужна повышенная бдительность.
O>Например, имя файла, получаемое через FltGetFileNameInformation, выделяется из paged-пула, поэтому тупо взять его и
O>запихнуть в такую очередь нельзя, нужно сначала где-нибудь в безопасном месте, например, на pre-create или на
O>post-create (там всегда PASSIVE_LEVEL) сделать копию имени в nonpaged-памяти.

O>Использовать FltDoCompletionProcessingWhenSafe или FLT_PREOP_SYNCHRONIZE здесь тоже не стоит, это только ухудшит

O>производительность системы.

А, кстати, что такое pre-create и post-create, у которых PASSIVE_LEVEL? FltGetFileNameInformation тут тоже используется. Проблем вроде BSODов не наблюдается никак. Однако меня больше интересует другое — раз там PASSIVE_LEVEL, то нельзя ли там синхронизировать? Но важно, чтобы решение поддерживало и IRP_MJ_WRITE.

> POST_OPERATION_CALLBACK в общем случае может вызываться на DISPATCH_LEVEL

А если просто отсечь случаи, когда он на нем вызывается? То можно ли будет использовать мьютексы и сможет ли система логировать все операции с файлами, в том числе IRP_MJ_WRITE и операции не только от usermode-приложений, но желательно и от других драйверов?

И что все-таки можно сделать? Я могу согласиться с тем, что решение делать такое жирное логирование в отдельном потоке драйвера — это плохое решение. Но само по себе использование отдельного потока, в который каждые N секунд\минут попадают данные из POST_OPERATION_CALLBACK, вроде бы не относится к такому — это может в некоторых случаях быть нужно. Поэтому хотя бы для общего развития хотелось бы найти решение.
(Ну а вообще я сам сторонник того, что у каждого драйвера, если это не драйвер устройства, должен быть свой сервис или приложение в usermode.)

Стоит ли заменить на UNICODE_STRING? В идеале, конечно, хотелось бы нормальный контейнер, как std::vector в C++. На C++ можно писать целый месяц и ни разу ничего не очищать, т.к. ничего и не выделяешь. Сюда бы тоже такое. Кстати, там еще и список один самодельный заменить надо, а то тоже течет. Или быстродействие и другие проблемы помешают реализовать подобное?