NXビット

NXビット (No eXecute bit) は、ノイマン型アーキテクチャのコンピュータにおいて特定のメモリ領域（に置かれたデータ）に付与する実行不可属性、またはその属性付与機能を指す。
概要.
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ワームのようなプログラムが挿入されて実行される事から保護する。これらの攻撃はメモリのある部分（通常はスタック）が書き込み可能でありかつ実行可能である事に依存している。よって、この条件を満たしていなければ攻撃は失敗する。
オペレーティングシステムにおける実装.
多くのオペレーティングシステム (OS) がNXの手段を実装もしくは保持しており、また数種のOSはNXエミュレーションを実装もしくは保持している。これはアルファベット順のOSリストである。それぞれ、技術は新しいものから古いものへの順となっている。
それぞれのOSの最初には、それぞれの技術がサポートする主要な機能が掲載されたデータ表がある。これらのOSの本質がその本質に関する情報の好都合な拡散を保証するので、これらの表は下記を要約するために提供されている。表は下記の構成となっている。
アーキテクチャ依存エミュレーションを供給するOSはハードウェアでサポートしていない全てのプロセッサ上で機能する。「その他のサポート」行はまだ明白ではない手段、たとえば明確なNXビットを搭載していないハードウェアが何らかの方法で機能を実現しているプロセッサのためにある。
OpenBSD.
W^X.
OpenBSDオペレーティングシステムの技術として知られるW^X (Write XOR Execute) はAMD64ポートで、このようなシステムにW^Xを最大限活用させるためにNX技術を利用している。W^Xは現在のOpenBSDではNXビットをサポートしていないCPUのW^Xもサポートする。
W^XはAlpha、AMD64、PA-RISCおよびSPARCプロセッサのNXビットをサポートする（しかしインテルのIntel 64は当初NX機能がなかったためこれをサポートしていないことは特筆に値する）。
OpenBSD 3.3は2003年5月1日にリリースされ、これが最初にW^Xを含んだものである。
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向けに多数のリリースにおいて存在している。
Exec Shield.
レッドハットのカーネル開発者Ingo MolnarはExec Shieldという32ビットx86CPUでLinuxがNX機能を活用できるようにするLinuxカーネルパッチを提供した。後にMolnarは32ビットカーネル上でハードウェアNXをサポートするLinux NXパッチを提供した。
Exec Shieldパッチは2003年5月2日にLinux Kernel Mailing Listに提供された。このパッチは、複雑なエミュレーションを実現するために基礎的なコードに重大な改変を加えるためカーネルには取り込まれなかった。
PaX.
PaXのNX技術はNXビットもしくはNX機能をエミュレートもしくはハードウェアのNXビットを使用することができる。PaXは32ビットのx86のようにNXビットを持っていないx86 CPUで使用することができる。
PaXプロジェクトは2000年の10月1日に開始された。これは後に2.6にポートされ、この記事を記載している時点では開発中である。
2004年5月現在ではLinuxカーネルはPaXを組み込んでリリースされていない。パッチは手動で統合する必要がある。
Solaris.
Solaris 10がNXビットをサポートしているプロセッサで起動した時、自動的に保護は有効となる。プログラムのスタックセグメントの過去の32ビットABIの取り扱いは例外となる。ほとんどのプログラムは変更なしに動作する。しかし既存のアプリケーションの起動時にSIGSEGVが発生する場合には、eeprom (1M) を使用してenforce-prot-execをoffにし再起動することによりNX機能を無効化することができる。バグはアプリケーションに対して報告することができるから、適切にPROT_EXECを使用するために更新することができる。詳細はeeprom(1M)のマニュアルページ及びmmap(2)マニュアルページのPROT_EXECを参照すること。
Windows.
Windows XP Service Pack 2とWindows Server 2003 Service Pack 1から、x86アーキテクチャでは初めてNX機能が実装された。
Windowsでは重要なWindowsのサービスのみにNXによる保護が使用される。Windows XPもしくはServer 2003では、この機能はデータ実行防止 (DEP) と呼ばれ、「マイ コンピュータ」の「詳細設定」より設定できる。もしx86プロセッサがハードウェアでこの機能をサポートしている場合、NX機能はWindows XP/Server 2003ではデフォルトで有効となる。機能がサポートされていない場合には、保護は提供されない。
「ソフトウェアDEP」はNXビットに関係なく、マイクロソフトが「安全な例外ハンドラ」に付けた名称である。「ソフトウェアDEP」や「安全な例外ハンドラ」は、アプリケーションのファンクションテーブルに例外が登録されていることを確認し、プログラムがそのように設計されていることを要求するものである。これは、DEPがNXフォールトを扱う方法により悪用可能な弱点を対策するものである。他の対策法がそのままプログラムを終了するのに対し、DEPは例外を発生させる。プログラムの流れは復旧不可能に破壊されているため、プログラムが攻撃から回復できるものではない。
他のほとんどの保護手法とは異なり、DEPはASLR（アドレス空間レイアウト無作為化）を提供しない。これはreturn-to-libc攻撃を許し、攻撃中にDEPを無効化するのに使用される可能性がある。Windowsでこれが実行可能であることは未だ証明されていないが、PaXの文書はなぜASLRが必要かを詳述している。もし破損した画像やMP3などの用意されたデータのアドレスが、攻撃者によって知られている場合には攻撃を成功させる可能性がある。ASLRはWindows Vistaから提供された。
x86以外では、インテルのIA-64で動作するWindows向けNXのバージョンが存在する。
同等技術間の機能的比較.
ここでは、NX技術の機能を比較対照する。
一般的に、NXビットのエミュレーションはx86CPUでのみ可能である。別に述べない限りこのセクションでのエミュレーションへの言及はx86CPUのみを対象としている。
あるNXビットエミュレーションの方法は大変低いオーバーヘッドを持っていることが証明されているが、そのような方法は不正確であるとも証明されている。一方、他のあるエミュレーション方法は大変高いオーバーヘッドを持っているかもしれないが、おそらく絶対に正確である。処理能力、正確性、仮想メモリ空間の代償なしにオーバーヘッドを減らす方法は現在では開発されていない。
オーバーヘッド.
オーバーヘッドはそれぞれの技術が機能するために必要な追加のCPU処理能力の事である。これはこのような技術をエミュレートもしくはNXビットを提供する事は通常測定可能なほどのオーバーヘッドを生じるために重要である。全てのNX技術はあらゆる領域のメモリのためにNXビットの状態を制御するために追加のプログラミングロジックのためにオーバーヘッドを作り出す。しかし、ハードウェアNXビットが存在すれば演算は通常CPU自身で行われ、オーバーヘッドは生じない。
ハードウェアNXビットを提供するCPUでは、特に明記する場合を除いてはリストされている全てのNX技術においてオーバーヘッドを生じない。