web-dev-qa-db-ja.com

gcc -D_FORTIFY_SOURCE = 1と-D_FORTIFY_SOURCE = 2の違い

誰かがgcc -D_FORTIFY_SOURCE=1-D_FORTIFY_SOURCE=2の違いを指摘できますか? =2の方が安全だと思いますか?ポイントごとに違いをリストしたリストを見つけることができませんでした。

また、-D_FORTIFY_SOURCE=2-O2とともに使用する必要があることも読んでいます。そうしないと、すべての機能が使用可能になりません。また、ここで私は詳細に回帰を指定するリストを見つけていません。ターゲットはフラッシュメモリがそれほど多くないデバイスなので、-Osでコンパイルすることに特に興味があります。

これが文書化されている場所に関するヒントは歓迎します!

58

機能テストマクロのマニュアルページから( man 7 feature_test_macros

_FORTIFY_SOURCE(glibc 2.3.4以降)

このマクロを定義すると、さまざまな文字列およびメモリ操作関数(たとえば、memcpymemsetstpcpystrcpystrncpystrcatstrncatsprintfsnprintfvsprintfvsnprintfgets、およびそれらのワイド文字バリアント)。一部の関数では、引数の一貫性がチェックされます。たとえば、指定されたフラグにO_CREATが含まれる場合、openmode引数が指定されているかどうかのチェックが行われます。すべての問題が検出されるわけではなく、いくつかの一般的なケースが検出されます。

_FORTIFY_SOURCEが1に設定され、コンパイラー最適化レベル1(gcc -O1)以上の場合、適合プログラムの動作を変更してはならないチェックが実行されます。

_FORTIFY_SOURCEを2に設定すると、さらにいくつかのチェックが追加されますが、一部の適合プログラムは失敗する可能性があります。

一部のチェックは、コンパイル時に(ヘッダーファイルに実装されたマクロロジックを介して)実行でき、コンパイラ警告が発生します。他のチェックは実行時に行われ、チェックが失敗すると実行時エラーが発生します。

このマクロを使用するには、バージョン4.0以降のgccで利用可能なコンパイラサポートが必要です。

さらに、記事 FORTIFY_SOURCEでアプリケーションのセキュリティを強化する (2014年3月)は次のように述べています。

  • gcc -D_FORTIFY_SOURCE=1はコンパイル時にのみチェックを追加します(#include <string.h>としていくつかのヘッダーが必要です)
  • gcc -D_FORTIFY_SOURCE=2は実行時にチェックも追加します(バッファーオーバーフローが検出されるとプログラムが終了します)

基本的に、_FORTIFY_SOURCEレベル2はより安全ですが、少し危険なコンパイル戦略です。使用する場合は、コンパイルしたコードに対して非常に強力な回帰テストを行い、コンパイラが予期しない動作を引き起こしていないことを確認してください。

46
Colonel Panic

http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.htmlfeature_test_macros(7) よりも詳細になります。

関連する抜粋は、わかりやすくするために軽く編集/再フォーマットされています。

_-D_FORTIFY_SOURCE=1_と_-D_FORTIFY_SOURCE=2_の違いは、たとえばために

_  struct S {
      struct T {
        char buf[5];
        int x;
      } t;
      char buf[20];
  } var;
_

_-D_FORTIFY_SOURCE=1_を使用すると、

_  strcpy (&var.t.buf[1], "abcdefg");
_

_-D_FORTIFY_SOURCE=2_の場合、オーバーフローと見なされません(オブジェクトはVAR全体)

_  strcpy (&var.t.buf[1], "abcdefg");
_

バッファオーバーフローと見なされます。

別の違いは、最も一般的な_-D_FORTIFY_SOURCE=2_ファミリー関数のフォーマット文字列の_%n_、_*printf_では、読み取り専用メモリ(通常は文字列リテラル、gettext_("%s string %n")も問題ありませんが)、通常、攻撃者がフォーマット文字列の脆弱性を悪用しようとすると、_%n_は攻撃者が書き込むことができる場所になります。

13
jjlin