So-net無料ブログ作成

FSDirWalker 1.0.180.1 BugFilx公開しました [ソフトウェア]

今回、「連載」はお休みしての割り込みです。FSDirWalkerのバグ修正版(1.0.180.1)を公開しました。

前回ブログで32767文字のパスについて、いい気になって偉そうにあれこれ書きながら動作確認したところ、いくつかバグを見つけてしまって修正に追われる事に。
(テストはしていたのですが、まだまだ不足しておりました…)

それらのバグの中に、Windows 7がブルースクリーンで停止するバグを発見し至急の修正となったものです。

カーネルがクラッシュするので重大なバグですが、FSDirWalkerにはカーネルモードモジュールは含まれていません。

これは、ユーザーモードで渡したパラメータが元でWindowsのカーネルモード側でクラッシュするもので、極々希にある様です(ドライバ自身や自作のカーネルモードモジュール、マルウェアなどではなくユーザーモード側からの操作という意味で)。

そのバグは、ファイルのリネーム時に起きたもので、リネーム後のパス+ファイル名が32767文字を超えるとブルースクリーンで落ちるというものでした。

特殊な処理である上、長大なパスやファイル名作成しなければならないので、通常の使用環境ではこの問題に直面することはまず無いと思います。

しかし、意図した操作をすれば100%再現性のあるBSODとなると放っておけないので、急ぎ修正版をリリースしました。


以下、具体的に説明します。
(FSDirWalkerでの再現例です)

あるボリュームに、次の様なルートディレクトリを基点としたパスを持つファイルがあるとします。

"\a\a....\a\zz"
全体で32767文字のパス、最後の"zz"はファイル名。

まず、ボリュームのルートディレクトリをオープンし、次にそのルートを親に残りった"a\a....\a"のディレクトリの部分をオープンします。更にそれを親にして最終的にファイル"zz"をオープンします。
そのファイルの名前を"zzz"にリネームしたいとします。その操作のためにネイティブAPIのNtSetInformationFile関数にFileRenameInformationを指定し、引数の構造体に新しい名前"zzz"を指定します。
ところが、もし、この操作が成功すると、自身の名前とすべての親の名前を合わせた全体のパスの長さは32768文字になってしまい、有効長の32767文字を超えることになります。

結果的に不正になるパラメータを渡す操作にも問題があるのですが、このケースは相対パスのファイル名で指定しているので、パス文字列の全体長が分かりにくい状況です。
ですので、NtSetInformationFileが何らかのエラーを返して欲しいところですが、Windows 7ではブルースクリーンが表示されて停止してしまいます。
以下は、クラッシュ時のメモリダンプからのスタックトレースです。

0: kd> k
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
a3e537cc 83641c48 nt!IoGetRelatedDeviceObject+0x80b
a3e53870 83a1fba9 nt!Kei386EoiHelper+0x27e0
a3e538bc 898846bc hal!KfLowerIrql+0x61
a3e53b04 898c0c0f Ntfs!NtfsSetRenameInfo+0x153e
a3e53b84 898161ae Ntfs!NtfsCommonSetInformation+0x674
a3e53bf0 83637d8d Ntfs!NtfsFsdSetInformation+0x107
a3e53c08 8957920c nt!IofCallDriver+0x64
a3e53c2c 895793cb fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2aa
a3e53c64 83637d8d fltmgr!FltpDispatch+0xc5
a3e53c7c 8385cae2 nt!IofCallDriver+0x64
a3e53d18 8363ea66 nt!NtSetInformationFile+0x953
a3e53d34 776c70f3 nt!ZwYieldExecution+0xb66
a3e53d38 badb0d00 ntdll!KiFastSystemCall+0x3

カーネルモードのNtSetInformationFileから始まり、ntfs.sysのリネーム処理の最中に引き起こされている模様です。

ここでは、ディレクトリやファイルを相対オープンしていますが、ボリューム名を含めた絶対パスでファイルをオープンしても、リネーム後の新しいパス+ファイル名が32767文字を超えてしまう様なら、同じ現象が起きます。

このバグは、手元の複数のWindows 7 SP1で必ず再現しました(64bit版でも発生)ので、私の環境特有という訳では無いと思いますが、MSのKnowledge Baseで探してみたところ私の探し方が悪いのか、掲載されていないのか見つけることができませんでした。どなたかご存知でしたらご教示ください。

なお、Windows 8.1、Windows 10では再現しませんでしたので何らかの修正が入ったのかもしれません。

Windows 7の不具合だとは思うのですが、修正は望めないのでFSDirWalker側で回避することにしました。
上記の様なリネームの処理の際、新しいパスが32767を超えない様にチェックする処理を追加しています。

なお、今回FSDirWalkerは他にもいくつかバグを修正していますので、興味がある方はこちらからどうぞ。

コメント(0) 

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。