トップ回答者
フィルタドライバで複数回検知した場合の対応について

質問
回答
-
> 作りたいものとしては、予め指定したファイルに対して、
> アクセスがあった場合にフィルタドライバにて検知して、
> ログを保存するアプリケーションを考えております。
> また特定のユーザーのみ指定したファイルを開けないよう
> 制御をするアプリケーションを考えております先の返信でも少し触れましたが、File System Mini-Filter には全ての File I/O に関する通知が来ます。
そしてその File I/O は、任意のファイル/ディレクトリに対する要求が、任意のタイミングで、任意の回数分通知されることになります。
「予め指定したファイル」への File I/O が特定の回数分しか来ない。。。ということはまずあり得ません。
例えばそのファイルを、セキュリティ対策ソフトや Windows Search Indexer Service (SearchIndexer.exe)、あるいはまったく知らない 3rd ベンダー製サービスやプリフェッチ機能が開くかもしれません。
そしてこれらプロセスがその「予め指定したファイル」を、「どんなタイミング」で「何回」開くのかを事前に把握することは、神様以外は不可能です。
なので File System Mini-Filter Driver 開発では、「任意のファイル/ディレクトリに対して、任意のタイミングで、任意の回数分 File I/O が来る」ことを大前提とする必要があります。
> 現状のサンプルでは、フィルタドライバにて検知したら
> ログを書き出すところまで作成できたのですが
> 質問させていただきました通り、1回ファイルを開いただけで
> 複数のログが書き出されておりその回避策を探していたところ
> になります。そもそも1回のユーザー オペレーションで、それに対応する Create IRP 通知が1回しか来ないはず。。。という認識は間違いです。
例えば Word / Excel などのアプリケーションでも、編集対象となるデータ ファイルへの Create IRP 通知は、複数回来ます。
しかも場合によっては、異なるプロセスのスレッド コンテキストから、Create IRP 通知が来ることすらあります。
「1回ファイルを開いただけで複数のログが書き出されており」というのは、まさにその通りの通知が来ているはずで、それに対する「回避策を探す」方がおかしいように思います。
File I/O をロギングするアプリ (ホントにアプリなのでしょうか? サービスでは?) を作りたいのであれば、ロギング情報を間引いてしまっては意味がないのでは?
なぜ通知された File I/O をわざわざ間引くのか、私にはその理由が良くわかりませんでした。
> こちら最初の通知か否かを判断する方法というのは、
> それらをする関数があるような形でしょうか
> それとも通知がされた際にファイル等に書き出して
> ログのような形で保存して、次以降そちらのファイルを参照して
> 判定するといったかたちになりますでしょうかそもそも Create IRP 通知を間引く目的でこの質問をされているなら本末転倒ですが、聞かれたので一応。。。
カレント プロセス情報を取得する関数とかはありますが、「最初の通知であるか」などを判断してくれる便利な関数はありません。
提示された要求仕様を見る限り、FltMgr.sys ドライバが提供する Mini-Filter Driver Routine (FltXxx 関数) だけでの実現は不可能なので、Process / Thread Manager Routine 等のサービス関数を併用する必要があります。
また「最初の通知であるか」を判断するための情報も、自身で保持する必要があります。
具体的には、ご自身でデータ オブジェクト (構造体) を定義し、そのデータ オブジェクト用のメモリ ブロックを Paged Pool あるいは Nonpaged Pool から確保し、ご自身で管理する必要があります。
ちなみに、File System Mini-Filter が自身で管理するデータをいちいちファイルに書き出していたら、即パフォーマンスに影響が出ます。
(下手をしたら、即 BSOD です。)
ご質問内容を読む限り、ドライバ。。。というより Windows プログラミングに関する知識と、開発しようとしているソフトウェア仕様に、かなりのかい離があるように感じます。
中途半端な知識で File System Mini-Filter Driver を開発し製品化してしまうと、後々自分たちでは対応不可能な問題に直面することになります。
なのでまずはデバッガを使って、File System Mini-Filter Driver に対して File I/O がどのように通知されてくるのか、じっくり観察されることを強くお勧めします。
(File System Mini-Filter Driver は簡単なようで、実は非常に奥が深いのです。)- 編集済み お馬鹿 2017年6月28日 8:27 誤記訂正
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年6月29日 0:45
- 回答としてマーク ParanoiaOops 2017年7月3日 4:50
すべての返信
-
> フィルタドライバのサンプルを組み立て、
> 検知を開始したところ単一のファイルに対して
> 複数回の検知がされることを確認いたしましたそれが Mini-FIlter の通常の挙動です。
> この時に1回だけ検知させたいのですが
> 何か方法はありますでしょうか具体的に何がしたいのかわからないのなんとも言えませんが、そもそも File System Mini-Filter への Create IRP 通知は、任意のファイルが任意のタイミングで任意の回数来ます。
なので「1回だけ検知」が、「Mini-Filter にコールバックされる Create IRP 通知を1回だけにしたい」という意味なのであれば、そもそもの認識に誤解があると思います。
「特定のプロセスに対しての最初の Create IRP 通知で何かをしたい」ということであれば、通知されたスレッドでのカレント プロセスをチェックし、そのプロセスでの最初の通知であるか否かを判断すれば可能です。
とにかく「要求仕様」を明確にされることをお勧めします。- 回答としてマーク ParanoiaOops 2017年6月28日 7:10
- 回答としてマークされていない ParanoiaOops 2017年6月28日 7:10
-
回答していただき、ありがとうございます。
> > フィルタドライバのサンプルを組み立て、
> > 検知を開始したところ単一のファイルに対して
> > 複数回の検知がされることを確認いたしました
> それが Mini-FIlter の通常の挙動です。
それが標準の仕様なのですね、承知いたしました。
>とにかく「要求仕様」を明確にされることをお勧めします。
作りたいものとしては、予め指定したファイルに対して、アクセスがあった場合に
フィルタドライバにて検知して、ログを保存するアプリケーションを考えております。
また特定のユーザーのみ指定したファイルを開けないよう制御をするアプリケーションを考えております
ログをためていくというアプリケーションを開発しております。
現状のサンプルでは、フィルタドライバにて検知したらログを書き出すところまで作成できたのですが
質問させていただきました通り、1回ファイルを開いただけで複数のログが書き出されており
その回避策を探していたところになります。
ちなみになのですが、回答いただきました
> 通知されたスレッドでのカレント プロセスをチェックし、そのプロセスでの最初の通知であるか否かを判断すれば可能です。
こちら最初の通知か否かを判断する方法というのは、それらをする関数があるような形でしょうか
それとも通知がされた際にファイル等に書き出してログのような形で保存して、次以降そちらのファイルを参照して
判定するといったかたちになりますでしょうか
もしよければ上記質問にも回答いただけると幸いです。
宜しくお願い致します。 -
> 作りたいものとしては、予め指定したファイルに対して、
> アクセスがあった場合にフィルタドライバにて検知して、
> ログを保存するアプリケーションを考えております。
> また特定のユーザーのみ指定したファイルを開けないよう
> 制御をするアプリケーションを考えております先の返信でも少し触れましたが、File System Mini-Filter には全ての File I/O に関する通知が来ます。
そしてその File I/O は、任意のファイル/ディレクトリに対する要求が、任意のタイミングで、任意の回数分通知されることになります。
「予め指定したファイル」への File I/O が特定の回数分しか来ない。。。ということはまずあり得ません。
例えばそのファイルを、セキュリティ対策ソフトや Windows Search Indexer Service (SearchIndexer.exe)、あるいはまったく知らない 3rd ベンダー製サービスやプリフェッチ機能が開くかもしれません。
そしてこれらプロセスがその「予め指定したファイル」を、「どんなタイミング」で「何回」開くのかを事前に把握することは、神様以外は不可能です。
なので File System Mini-Filter Driver 開発では、「任意のファイル/ディレクトリに対して、任意のタイミングで、任意の回数分 File I/O が来る」ことを大前提とする必要があります。
> 現状のサンプルでは、フィルタドライバにて検知したら
> ログを書き出すところまで作成できたのですが
> 質問させていただきました通り、1回ファイルを開いただけで
> 複数のログが書き出されておりその回避策を探していたところ
> になります。そもそも1回のユーザー オペレーションで、それに対応する Create IRP 通知が1回しか来ないはず。。。という認識は間違いです。
例えば Word / Excel などのアプリケーションでも、編集対象となるデータ ファイルへの Create IRP 通知は、複数回来ます。
しかも場合によっては、異なるプロセスのスレッド コンテキストから、Create IRP 通知が来ることすらあります。
「1回ファイルを開いただけで複数のログが書き出されており」というのは、まさにその通りの通知が来ているはずで、それに対する「回避策を探す」方がおかしいように思います。
File I/O をロギングするアプリ (ホントにアプリなのでしょうか? サービスでは?) を作りたいのであれば、ロギング情報を間引いてしまっては意味がないのでは?
なぜ通知された File I/O をわざわざ間引くのか、私にはその理由が良くわかりませんでした。
> こちら最初の通知か否かを判断する方法というのは、
> それらをする関数があるような形でしょうか
> それとも通知がされた際にファイル等に書き出して
> ログのような形で保存して、次以降そちらのファイルを参照して
> 判定するといったかたちになりますでしょうかそもそも Create IRP 通知を間引く目的でこの質問をされているなら本末転倒ですが、聞かれたので一応。。。
カレント プロセス情報を取得する関数とかはありますが、「最初の通知であるか」などを判断してくれる便利な関数はありません。
提示された要求仕様を見る限り、FltMgr.sys ドライバが提供する Mini-Filter Driver Routine (FltXxx 関数) だけでの実現は不可能なので、Process / Thread Manager Routine 等のサービス関数を併用する必要があります。
また「最初の通知であるか」を判断するための情報も、自身で保持する必要があります。
具体的には、ご自身でデータ オブジェクト (構造体) を定義し、そのデータ オブジェクト用のメモリ ブロックを Paged Pool あるいは Nonpaged Pool から確保し、ご自身で管理する必要があります。
ちなみに、File System Mini-Filter が自身で管理するデータをいちいちファイルに書き出していたら、即パフォーマンスに影響が出ます。
(下手をしたら、即 BSOD です。)
ご質問内容を読む限り、ドライバ。。。というより Windows プログラミングに関する知識と、開発しようとしているソフトウェア仕様に、かなりのかい離があるように感じます。
中途半端な知識で File System Mini-Filter Driver を開発し製品化してしまうと、後々自分たちでは対応不可能な問題に直面することになります。
なのでまずはデバッガを使って、File System Mini-Filter Driver に対して File I/O がどのように通知されてくるのか、じっくり観察されることを強くお勧めします。
(File System Mini-Filter Driver は簡単なようで、実は非常に奥が深いのです。)- 編集済み お馬鹿 2017年6月28日 8:27 誤記訂正
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年6月29日 0:45
- 回答としてマーク ParanoiaOops 2017年7月3日 4:50