未来のいつか/hyoshiokの日記

hyoshiokの日々思うことをあれやこれや

Linux Kernel NX Support

たまにはLinux Kernelの話も書こうということで昨日もちょっとふれた、NXサポートのお話。NXというのはLinuxのページに実行不可の属性を付ける機能だ。なんでそんな機能が必要かというと最近問題になっているワームとかウイルスみたいな外部からの悪意を持って送り込まれるコードの実行を防止できる場合があるからだ。

バッファーオーバフローの脆弱性を利用した攻撃の場合、悪意のあるコードは例えばスタック領域あたりにおかれるのだけれど、スタック領域を実行不可にできれば、ウイルスないしワームのコードは実行できなくなる。と、そーゆー話である。

Intelの32ビットアーキテクチャ(よくX86とか、IA32とかよばれるやつ)はあるページが実行可能かどうかを示すフラグがなかったのだけれど、IA32Eとよばれる64ビット拡張のアーキテクチャから実行不可のフラグが追加された。(XD -- eXecution Disable) IA32Eより先にAMD64で導入されたらしい。

それようのパッチが
http://people.redhat.com/mingo/nx-patches/nx-2.6.7-rc2-bk2-AE
にあるのでちょっと読んでみる。

--- linux/include/asm-i386/pgtable.h.orig	
+++ linux/include/asm-i386/pgtable.h	
@@ -110,6 +110,7 @@ void paging_init(void);
 #define _PAGE_BIT_UNUSED1	9	/* available for programmer */
 #define _PAGE_BIT_UNUSED2	10
 #define _PAGE_BIT_UNUSED3	11
+#define _PAGE_BIT_NX		63
 
 #define _PAGE_PRESENT	0x001
 #define _PAGE_RW	0x002
@@ -126,28 +127,51 @@ void paging_init(void);
 
 #define _PAGE_FILE	0x040	/* set:pagecache unset:swap */
 #define _PAGE_PROTNONE	0x080	/* If not present */
+#ifdef CONFIG_X86_PAE
+#define _PAGE_NX	(1ULL<<_PAGE_BIT_NX)
+#else
+#define _PAGE_NX	0
+#endif

NXのビットが63ビット目(#define _PAGE_BIT_NX 63)だということが分かる。
_PAGE_NXが1だと実行不可である。ページテーブルの属性に_PAGE_NXが立っていると実行できない。

--- linux/arch/i386/mm/fault.c.orig	
+++ linux/arch/i386/mm/fault.c	
@@ -406,6 +406,21 @@ no_context:
 
 	bust_spinlocks(1);
 
+#ifdef CONFIG_X86_PAE
+	{
+		pgd_t *pgd;
+		pmd_t *pmd;
+
+
+
+		pgd = init_mm.pgd + pgd_index(address);
+		if (pgd_present(*pgd)) {
+			pmd = pmd_offset(pgd, address);
+			if (pmd_val(*pmd) & _PAGE_NX)
+				printk(KERN_CRIT "kernel tried to access NX-protected page - exploit attempt? (uid: %d)\n", current->uid);
+		}
+	}
+#endif

ここでpgdはページグローバルディレクトリ、pmdはページミドルディレクトリであるページにアクセスする時に利用する。そのページに_PAGE_NXフラグが立っているとKERN_CRITというカーネルエラーを出す。
Linuxカーネルの詳細に関しては詳解LINUXカーネル(第二版)ISBN:4873111331。ページテーブルの話は64ページあたりに載っている。

プログラムのコードをそのまま表示するにはどうしたらいいのでしょう>教えてはてなダイアリー