GNU/Linux >> Linux の 問題 >  >> Linux

x86/x86_64 でアラインされていないメモリ アクセスを禁止する

GCC と Clang の両方に UndefinedBehaviorSanitizer が組み込まれています。これらのチェックの 1 つ、 alignment-fsanitize=alignment で有効にできます .実行時にポインターのアライメントをチェックし、アライメントされていないポインターが逆参照された場合は中止するコードを出力します。

次のオンライン ドキュメントを参照してください:

  • https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

難しいので個人的にはやったことはありませんが、次の方法でできると思います:

x86_64 CPU (具体的には Intel Corei7 をチェックしましたが、他の CPU も同様だと思います) には、ミスアラインされたメモリ参照に対処するパフォーマンス カウンター MISALIGN_MEM_REF があります。

まず第一に、プログラムを実行し、Linux で「perf」ツールを使用して、コードが行ったミスアライメント アクセスの数を取得できます。

よりトリッキーで興味深いハックは、オーバーフロー時に割り込みを生成し、最初のアライメントされていないロード/ストアをオーバーフローさせるようにパフォーマンス カウンターをプログラムするカーネル モジュールを作成することです。カーネルモジュールでこの割り込みに応答しますが、プロセスにシグナルを送信します。

これにより、事実上、x86_64 が非整列アクセスをサポートしないコアに変わります。

ただし、これは単純ではありません。コード以外に、システム ライブラリもアライメントされていないアクセスを使用するため、それらを独自のコードから分離するのは難しいでしょう。


ちょうど質問を読んだところです アライメントされていないメモリアクセスは常にバスエラーを引き起こしますか?ウィキペディアの記事セグメンテーション フォールトにリンクしています。

この記事には、あまり一般的ではない Intel プロセッサ フラグ AC (別名アライメント チェック) についての素晴らしいリマインダーがあります。

そして、これを有効にする方法は次のとおりです (ウィキペディアのバスエラーの例から、x86-64 System V 用に修正されたレッドゾーンクロバーバグを使用して、これは Linux および MacOS で安全であり、基本的な asm から変換されますが、関数内では決して良い考えではありません:AC への変更を、メモリ アクセスに対して順序付けする必要があります。

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\n orl $0x40000,(%%esp)\n popf" ::: "memory");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("add $-128, %%rsp \n"    // skip past the red-zone, in case there is one and the compiler has local vars there.
            "pushf\n"
            "orl $0x40000,(%%rsp)\n"
            "popf \n"
            "sub $-128, %%rsp"       // and restore the stack pointer.
           ::: "memory");       // ordered wrt. other mem access
# endif
#endif

有効にすると、/proc/cpu/alignment の ARM アライメント設定と同じように機能します。 、回答を参照してください。整列されていないメモリアクセスをトラップするには?たとえば。

さらに、GCC を使用している場合は、-Wcast-align を有効にすることをお勧めします。 警告。厳密なアラインメント要件 (ARM など) を持つターゲット用にビルドする場合、GCC はアラインされていないメモリ アクセスにつながる可能性のある場所を報告します。

ただし、me​​mcpy およびその他の関数に対する libc の手書きの asm は依然として非整列アクセスを行うため、AC を設定することは x86 (x86-64 を含む) では実用的でないことが多いことに注意してください。 GCC は、ソースがアラインされていなくても、アラインされていないアクセスを行う asm を出力することがあります。 2 つの隣接する配列要素または構造体メンバーを一度にコピーまたはゼロにするための最適化として。


Linux
  1. Linuxでメモリキャッシュをクリアする方法

  2. Linux –実際のメモリ使用量?

  3. Grep:メモリが使い果たされましたか?

  1. メモリの監視と管理

  2. PHPのメモリ制限

  3. realloc は posix_memalign のメモリ アラインメントを維持しますか?

  1. プログラムのRAM使用量を測定しますか?

  2. ページサイズがアラインされたメモリをどのように割り当てますか?

  3. Jenkins アクティブ (終了)