NXビット

概要

NXビットは、端的に言えば「データの誤実行」を防ぐために用いられる。そのしくみは、メモリをコード（プロセッサ命令）領域とデータ領域とに分離し、データを配置したメモリ領域にあらかじめ特別な印（属性）を付与することで、この領域のデータを実行しないようにする（実行を試みた際に例外＝エラーを発行する）ものである。
典型的には、バッファオーバーラン攻撃（後述）等に代表される、ヒープやスタック領域等に置かれたデータを破壊ないしは書き換えて任意のコードを挿入し実行を誘う攻撃を、オペレーティングシステムとCPUの協調により保護するために用いられる機能である。
その機能自体は、汎用機やワークステーション等の分野では既に特に目新しいものではなかったが、パーソナルコンピュータ用に最も普及したIA-32/AMD64アーキテクチャにおける実装は比較的最近の出来事であり、最初に実装したAMD64系列が搭載したものを"NXbit"と呼称したため、一般にはこの名称が普及した。
ノイマン型アーキテクチャのコンピュータでは、プログラムをメモリ上にデータとして読み込み、逐次実行する。メモリを読み取った際それがデータであるかプログラムであるのかを、単にメモリ上のデータのみをもって判断することは、ノイマン型では本質的に不可能である。バッファオーバーラン（バッファーオーバーフロー）等と呼ばれる攻撃は、ノイマン型コンピュータのこのような性質を悪用して行われる。
なお、インテルはこの機能をXDビット (eXecute Disable) と称している。しかしながら、インテルのXDビットとAMDのNXビットは同一の機能を持ち、従って名称以外は全く同一のものである。

ハードウェアの背景

x86プロセッサは80286以来セグメントレベルで実装された近い機能を持っていた。しかしこのメモリ管理モデルは特にフラットメモリモデルを採用する近年のソフトウェアで使うには粗末なものであり、セグメントではなくページ単位で実行を制御する新しい機構が求められていた。
このページレベルの機構は、ここ数年でサン・マイクロシステムズのSPARC、DECのAlpha、IBMのPowerPCといったx86プロセッサでない他のアーキテクチャのCPUで装備されてきた。インテルは2001年にIA-64アーキテクチャのItanium（コードネーム"Merced"）プロセッサで同様の機能を装備したが、より一般的なx86プロセッサ（Pentium、Celeron、Xeonなど）には装備しなかった。x86プロセッサの機能としてはAMDがAMD64シリーズ（Athlon 64、Opteronなど）で実装し、「NXビット」と呼んでいる。「NXビット」という用語は現在、他のプロセッサの似た技術を指し示す場合にも使われるようになってきた。
AMDがx86プラットホームを強化するという決定の後、インテルもインテルのx86プラットフォームも強化する事を決定し、Prescottコアを持ちLGA775ソケットを実装したPentium 4プロセッサから近い機能を装備した。
NXビットはx86プロセッサのページテーブルエントリ内の63番目ビットを明確に参照する（最後のビット、64ビット整数で最初のビットが0で始まる場合）。このビットが0にセットされていればコードはそのページから実行される。1にセットされていれば、コードはそのページから実行することはできず、そのページの全てはデータとして扱われる。またこれらのページはx86本来のページテーブルフォーマットではなく、物理アドレス拡張ページテーブルフォーマットに準拠している必要がある。

機能のソフトウェアエミュレーション

この機能がハードウェアに搭載される前には、数々のオペレーティングシステムが、W^XまたはExec Shieldなど、ソフトウェアを通してこの機能を実現しようとした。これらはこの記事の最後の方で解説される。
NXビットの機能を利用可能、もしくはエミュレート可能なオペレーティングシステム (OS) は、スタックもしくはヒープメモリ領域が実行可能になる事から保護し、実行可能メモリが書き込み可能になる事から保護できる。これはスタックオーバーフロー攻撃、特にSasserやBlasterワームのようなプログラムが挿入されて実行される事から保護する。これらの攻撃はメモリのある部分（通常はスタック）が書き込み可能でありかつ実行可能である事に依存している。よって、この条件を満たしていなければ攻撃は失敗する。

NetBSD

NetBSD 2.0およびそれ以降の時点では（2004年12月9日）、NXビットをサポートするアーキテクチャは実行可能ではないスタックとヒープを持つ。
AMD64、SPARC64、SPARC (sun4m, sun4d)、PowerPC (ibm4xx)、Alpha、SH5およびPA-RISCよりなるこれらはページ毎の粒度をもつ。
PowerPC（例:macppc）、80386はリージョン粒度のみをサポートする。
NetBSDはデフォルトではNXビットの機能を提供するいかなるソフトウェアも使用していないため、他のアーキテクチャは実行可能でないスタックやヒープからの恩恵は受けない。

Linux

Linux自身は標準のハードウェアNXをサポートする。現在は64ビットCPUにおいてもNXをサポートする64ビットモードと同様にIngo MolnarのNX有効化パッチにより32ビットモードでもサポートしている。これには現在のAMDの64ビットCPUとインテル、トランスメタおよびVIAから発表のあった将来のCPUも含まれる。リーナス・トーバルズはNXパッチに興味を持ち、標準で有効とされるべきだと考え2.6.8 releaseからは標準装備となった。これは32ビットのx86CPUおよび64ビットのx86互換CPUにて実行する32ビットのx86カーネルにおいては重要である。32ビットのx86カーネルはAMD64やIA-64が提供するNXビットを通常予期しない。NX有効化パッチはカーネルがもしNXビットが存在したら使用するようにさせる。
このパッチ時点では、LinuxはIntel, AMD, TransmetaおよびVIAが提供するNXビットをサポートしたCPUにおいてはハードウェアNXを完全に活用している。このNXパッチはLinux Kernel Mailing Listにおいて2004年6月に提供された。
同様の技術はx86でないCPU向けに多数のリリースにおいて存在している。

Solaris

Solaris 10がNXビットをサポートしているプロセッサで起動した時、自動的に保護は有効となる。プログラムのスタックセグメントの過去の32ビットABIの取り扱いは例外となる。ほとんどのプログラムは変更なしに動作する。しかし既存のアプリケーションの起動時にSIGSEGVが発生する場合には、eeprom (1M) を使用してenforce-prot-execをoffにし再起動することによりNX機能を無効化することができる。バグはアプリケーションに対して報告することができるから、適切にPROT_EXECを使用するために更新することができる。詳細はeeprom(1M)のマニュアルページ及びmmap(2)マニュアルページのPROT_EXECを参照すること。

同等技術間の機能的比較

ここでは、NX技術の機能を比較対照する。
一般的に、NXビットのエミュレーションはx86CPUでのみ可能である。別に述べない限りこのセクションでのエミュレーションへの言及はx86CPUのみを対象としている。
あるNXビットエミュレーションの方法は大変低いオーバーヘッドを持っていることが証明されているが、そのような方法は不正確であるとも証明されている。一方、他のあるエミュレーション方法は大変高いオーバーヘッドを持っているかもしれないが、おそらく絶対に正確である。処理能力、正確性、仮想メモリ空間の代償なしにオーバーヘッドを減らす方法は現在では開発されていない。

オーバーヘッド

オーバーヘッドはそれぞれの技術が機能するために必要な追加のCPU処理能力の事である。これはこのような技術をエミュレートもしくはNXビットを提供する事は通常測定可能なほどのオーバーヘッドを生じるために重要である。全てのNX技術はあらゆる領域のメモリのためにNXビットの状態を制御するために追加のプログラミングロジックのためにオーバーヘッドを作り出す。しかし、ハードウェアNXビットが存在すれば演算は通常CPU自身で行われ、オーバーヘッドは生じない。
ハードウェアNXビットを提供するCPUでは、特に明記する場合を除いてはリストされている全てのNX技術においてオーバーヘッドを生じない。