NXビットはセキュリティだけの話ではない

The NX bit is not just about security

ARM64ベアメタルハイパーバイザー開発中に発生した謎のフリーズの原因を追うデバッグ記録。CTR_EL0インターセプトを有効にするとランダムにシステムがロックアップする現象を、バイナリバイセクションやアセンブリ比較などの手法で切り分けていくと、最終的に分岐予測の誤予測が原因である可能性にたどり着く。

動的ディスパッチは分岐予測を利用し、静的ブランチは事前にどこへ向かうかを知っており誤予測することはありません。
  1. repiret

    「投機的インストラクションフェッチがデバイスメモリにアクセスするとデバイスがクラッシュする」は、私がこれまでに見つけた中で最も好きなバグの一つです。MPUのないCortex-M4でこれに遭遇したことがあり、メモリ属性を修正することすらできず、唯一の解決策はコンパイルされたコードを操作して投機的フェッチを防ぐことでした。

    Armv8/9-Aがデバイスメモリへの投機的インストラクションフェッチを許可しているのは驚きです。あまりに驚いたので、調べてみないと信じられませんでした:

    「ハードウェアは、メモリ位置がすべての例外レベルでexecute-neverとしてマークされていない限り、Deviceメモリ属性を持つメモリ位置への投機的インストラクションフェッチを防止しません。」 - ARM DDI 0487K.a § B2.15.2

    Armv7-M仕様はあまり明確ではありません。それにはこうあります:「アーキテクチャはDeviceとしてマークされたメモリへの投機的アクセスを許可しません」と。これはArmv8/9-Aが同様の文を「データアクセス」と限定しているのとは対照的です。しかしその後、「正確性を確保するために、読み取りに敏感な場所は非実行可能としてマークされなければなりません」とも述べています。(これはすべてARM DDI 0403E.e § A3.5.7からの引用です)

    比較するために古いv7-Aの仕様が手元にあればいいのですが。

  2. asveikau

    セキュリティだけの話ではないというこのテーマについて:use after freeのようなバグがあり、それがたまたま関数ポインタを覆った場合、NXビットにより、そのポインタを呼び出しで辿るときに、失敗点にできるだけ近い場所でクリーンなトラップが発生することを保証できます。もし古いバイトを盲目的にコードとして実行していたら、クラッシュやスタックトレースはそれほどきれいにはならないかもしれません。

    しかし、そのような正確性のバグの多くはセキュリティ問題でもあります。

  3. anyfoo

    最近では、アドレス0に何かをマップするのは悪い作法とされています... その理由の一つがこれでわかったでしょう!

    私が知っているケースでは、アドレス空間の1:1 IDマッピングがあり、物理アドレス空間には実際には0に何もないので、それでもマップする必要はありません。

  4. mubbicles

    この記事はありがたかったです。CSP担当者に違いを尋ねたことがありますが、この記事のおかげでdeviceとnsの違いをよりよく理解できました。また、これがAIが書いたものではないように見えるのも良いと思います。

  5. tripdout

    これを本当に理解できたらいいのにと思います。聞いたことのある、そして面白い(または面白そうな)トピックに触れているのですが、私にはそれを追うのに十分な知識がありません。NXビット(これは理解できます)と投機的アクセスの間の関連がわかりません。

この日のほかの記事

2026-09-07