FIO08-C. オープンしたままのファイルに対する remove() の呼び出しに注意する
オープンしたままのファイルに対して remove() を呼び出した場合の動作は、処理系定義である。一時ファイルは攻撃を受けやすいため、ファイル名を隠すためにオープンしたファイルを削除することが推奨されることがある(「FIO43-C. 共有ディレクトリに一時ファイルを作成しない」を参照)。
オープンしたままのファイルを削除する必要がある場合は、POSIX の unlink() 関数など、その動作が細かく規定されている関数の使用を検討すべきである。言語規格に厳密に合致し、可搬性を確保するには、オープンしたままのファイルに対して remove() を呼び出すべきでない。
違反コード
以下のコード例はオープンしたファイルを削除する。
char *file_name; FILE *file; /* file_name を初期化 */ file = fopen(file_name, "w+"); if (file == NULL) { /* エラー条件の処理 */ } /* ... */ if (remove(file_name) != 0) { /* エラー条件の処理 */ } /* ファイルへの I/O 処理を続行 */ fclose(file);
ストリームはオープンしたままであるため、処理系によっては file_name で指定したファイルは削除されない。
処理系固有の詳細
Microsoft Visual Studio C++ 2005 を使用してコンパイルされ Microsoft Windows XP 上で実行されるコードは、ファイルがオープンした状態では remove() は失敗し、関数の実行が終了した後もファイルへのリンクはそのまま残る。
適合コード (POSIX)
以下の解決法は、POSIX の unlink() 関数を使用してファイルを削除している。unlink() 関数はファイルシステム階層からファイルのリンクを確実に削除するが、そのファイルのオープンしたストリームがすべてクローズするまでディスクからファイルを削除しない [Open Group 04]。
FILE *file; char *file_name; /* file_name を初期化 */ file = fopen(file_name, "w+"); if (file == NULL) { /* エラー条件の処理 */ } if (unlink(file_name) != 0) { /* エラー条件の処理 */ } /*... ファイルへの I/O 処理を続行 */ fclose(file);
リスク評価
オープンしたままのファイルに対して remove() を呼び出した場合の結果は処理系によって異なる。削除したファイルの読み書きを行った場合に異常終了が引き起こされたり、意図したとおりにファイルが削除されなかった場合に予期せぬ情報漏えいが引き起こされることがある。
レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
FIO08-C | 中 | 中 | 高 | P4 | L3 |
自動検出
Compass/ROSE はこのレコメンデーションのいくつかの違反を検出できる。
参考情報
- [ISO/IEC 9899:1999] Section 7.19.4.1, "The removefunction"
- [Open Group 04] unlink()
翻訳元
これは以下のページを翻訳したものです。