4

次のコードを検討してください。

volatile int status;

status = process_package_header(&pack_header, PACK_INFO_CONST);

if ((((status) == (SUCCESS_CONST)) ? ((random_delay() && ((SUCCESS_CONST) == (status))) ? 0 : side_channel_sttack_detected()) : 1))
{
    ...
}

このマシンコードを生成します (ツールチェーンのobjdumpで生成されます):

  60:   f7ff fffe       bl      0 <process_package_header>
  64:   9000            str     r0, [sp, #0]     /* <- storing to memory as status is volatile */
  66:   42a0            cmp     r0, r4           /* <- where is the load before compare? status is volatile, it could have change between the last store instruction (above line) and now */
  68:   d164            bne.n   134 <func+0x134>
  6a:   f7ff fffe       bl      0 <random_delay>

現在、は揮発性であるため、ステートメントに到達statusしたときにメモリから読み取られているはずです。関数からの戻り値が割り当てられ、メモリに格納されているという事実に関係なく、 ( ) をifと比較する前に、いくつかのロード コマンドが表示されることを期待します。cmpSUCCESS_CONSTprocess_package_header()statusstrcmp

条件の動機を無視するようにしてくださいif。その目的は、条件フラグとレジスタが物理的な機器によって外部から変更される可能性のある CPU に対する物理的な攻撃を検出することです。

ツールチェーン ARM DS-5_v5.27.0 ARMコンパイラ: ARMCompiler5.06u5 (armcc)

ターゲットはARM CortexM0+ CPU

4

2 に答える 2

4

C11 6.7.3/7volatileから、オブジェクトを管理する主なルールは次のとおりです。

そのようなオブジェクトを参照する式は、5.1.2.3 で説明されているように、抽象マシンの規則に従って厳密に評価されます。さらに、すべてのシーケンス ポイントで、オブジェクトに最後に格納された値は、前述の未知の要因によって変更された場合を除き、抽象マシンによって規定された値と一致する必要があります。

そして続けてこう言います。

volatile 修飾された型を持つオブジェクトへのアクセスを構成するものは、実装によって定義されます。

これは、他の規則 (たとえば 5.1.2.3 の規則) がどのように解釈されるかに適用されます。コンパイラのユーザーズ ガイドでは、揮発性アクセスの詳細について説明していますが、そこには驚くべきことは何もないようです。セクション 5.1.2.3 自体は、主に順序付けルールについて説明しています。式を評価するためのルールは別の場所にあります (ただし、揮発性オブジェクトへのアクセスに関しては、与えられたとおりに従う必要があります)。

抽象マシンの動作に関連する詳細は次のとおりです。

  1. 代入操作には、 で識別されるオブジェクトに値を格納するという副作用がありますstatus。そのステートメントの最後にシーケンス ポイントがあるので、

    • 副作用は、後続のステートメントに現れる評価が実行される前に適用されます。
    • 揮発性であるためstatus、その行で表される割り当ては、シーケンスポイントの前にプログラムによって実行された最後の書き込みです。status
  2. ifステートメント内の条件式が次に評価されます。

    • 部分式(status) == (SUCCESS_CONST)が最初に評価され、他の部分式より前に評価されます。
    • の評価は操作statusの評価の前に発生し、==
    • その識別子を、それが識別するオブジェクトに格納されている値に変換する形式を取ります (パラグラフ 6.3.2.1/2 による左辺値変換)。
    • その時点で 格納され ている値で何かを行うには、まずその値を読み取る必要があります。status

標準では、揮発性オブジェクトがアドレス可能なストレージに常駐する必要がないため、原則として、揮発性自動変数をレジスターに排他的に割り当てることができます。その場合、そのオブジェクトを使用する機械語命令がその値をレジスタから直接読み取るか、レジスタを直接更新する限り、適切な揮発性セマンティクスを実現するために個別のロードまたはストアは必要ありません。ただし、生成されたアセンブリのストア命令は、実際にメモリ内の場所に関連付けられていることを示しているように見えるため、特定のオブジェクトはこのカテゴリに分類されないようです。

さらに、プログラムがレジスタに割り当てられたオブジェクトの揮発性セマンティクスを正しく実装した場合、そのレジスタは r0 でなければなりません。このアセンブリ言語とコードが実行されるプロセッサの詳細については詳しくありませんが、r0 がそのようなストレージの実行可能な場所であるようには見えません。

その場合、メモリから読み戻されるべきであり、条件式での2回目の出現を評価する必要がある場合は、メモリから再度status読み戻されるべきであることに同意します。これは、すべての揮発性アクセスに関して適合する実装が示す抽象マシンの動作です。私の分析では、あなたの実装はこの点で不適合であり、バグとして報告したいと思います。

回避策として、重要なビットをアセンブリに書き込むのが最善の策だと思います-実装がサポートしている場合はインラインアセンブリ、または必要に応じてアセンブリに実装された完全な関数として。

于 2019-04-01T19:11:42.717 に答える