[インデックス 13609] ファイルの概要
このコミットは、Go言語のリンカであるcmd/5l
(ARMアーキテクチャ向け)に、ELFヘッダにPT_PAX_FLAGS
という新しいプログラムヘッダを追加する変更を導入しています。これにより、PAX(Program Analysis eXecutor)セキュリティ機能が有効なARMカーネル環境において、生成される実行ファイルのセキュリティ属性を適切に設定できるようになります。
コミット
cmd/5l: add PT_PAX_FLAGS ELF header
Although I don't use PAX enabled ARM kernels, PAX
does have support for ARM, so we're better off add
PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6453092
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/af92b29fe63bd68b3892f6773b3da5892f6773b3da5896db52e6e
元コミット内容
commit af92b29fe63bd68b3892f6773b3da5896db52e6e
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Thu Aug 9 08:47:43 2012 +0800
cmd/5l: add PT_PAX_FLAGS ELF header
Although I don't use PAX enabled ARM kernels, PAX
does have support for ARM, so we're better off add
PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6453092
---
src/cmd/5l/asm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 3e51ece462..e39fcc9641 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
## 変更の背景
この変更の背景には、Go言語で生成される実行ファイルが、PAX(Program Analysis eXecutor)セキュリティ機能が有効なLinuxカーネル環境、特にARMアーキテクチャ上で適切に動作し、かつセキュリティ上の恩恵を受けられるようにするという意図があります。
コミットメッセージには「Although I don't use PAX enabled ARM kernels, PAX does have support for ARM, so we're better off add PT_PAX_FLAGS now in case people use PAX kernels.」と明記されています。これは、コミットの作者自身はPAXが有効なARMカーネルを使用していないものの、PAXがARMをサポートしているため、将来的にPAXカーネルを使用するユーザーのために、現時点で`PT_PAX_FLAGS`を追加しておくことが望ましいという判断を示しています。
PAXは、様々なメモリ保護メカニズムを実装することで、バッファオーバーフローなどの一般的な脆弱性を悪用した攻撃を防ぐことを目的としたLinuxカーネルのパッチセットです。これらのセキュリティ機能は、実行ファイルが特定のセキュリティ属性を持つことを期待します。`PT_PAX_FLAGS`プログラムヘッダは、実行ファイルがこれらのPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるための標準的な方法です。このヘッダを追加することで、Go言語でビルドされたバイナリがPAX環境下で予期せぬ挙動をすることなく、またPAXが提供するセキュリティ保護を最大限に活用できるようになります。
## 前提知識の解説
このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。
### 1. ELF (Executable and Linkable Format)
ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている実行可能ファイル、オブジェクトファイル、共有ライブラリ、およびコアダンプファイルの標準フォーマットです。ELFファイルは、プログラムの実行に必要なすべての情報(コード、データ、シンボルテーブル、再配置情報など)を構造化された形式で格納します。
ELFファイルは主に以下のセクションで構成されます。
* **ELFヘッダ**: ファイルのタイプ(実行可能ファイル、オブジェクトファイルなど)、アーキテクチャ、エントリポイントアドレスなど、ファイル全体の基本的な情報を含みます。
* **プログラムヘッダテーブル (Program Header Table)**: 実行可能ファイルや共有ライブラリにのみ存在し、プログラムのロード方法を記述します。各エントリ(プログラムヘッダ)は、メモリセグメントのタイプ、ファイル内のオフセット、メモリ上のアドレス、サイズ、アクセス権限(読み取り、書き込み、実行)などを定義します。
* **セクションヘッダテーブル (Section Header Table)**: オブジェクトファイルや共有ライブラリに存在し、ファイル内の各セクション(.text, .data, .bssなど)の属性を記述します。
* **セクション**: 実際のコードやデータが格納される領域です。
### 2. プログラムヘッダ (Program Header) とそのタイプ
プログラムヘッダは、ELFファイルがメモリにロードされる方法をカーネルに指示する構造体です。各プログラムヘッダは、`p_type`フィールドによってその種類が定義されます。一般的なタイプには以下のようなものがあります。
* `PT_LOAD`: メモリにロードされるセグメントを記述します。実行可能コードや初期化されたデータなどがこれに該当します。
* `PT_INTERP`: プログラムインタプリタ(例: `/lib/ld-linux.so.2`)のパスを記述します。
* `PT_DYNAMIC`: 動的リンク情報を含むセグメントを記述します。
* `PT_NOTE`: ノートセクション(特別な情報)を記述します。
### 3. PAX (Program Analysis eXecutor)
PAXは、Linuxカーネルのセキュリティ強化パッチセットであり、様々なメモリ保護技術を実装して、一般的なソフトウェアの脆弱性(特にメモリ破損の脆弱性)を悪用した攻撃を防ぐことを目的としています。PAXが提供する主なセキュリティ機能には以下のようなものがあります。
* **Non-Executable Pages (NX/DEP)**: データセグメントからのコード実行を防ぎます。これにより、スタックやヒープに注入されたシェルコードの実行を困難にします。
* **Address Space Layout Randomization (ASLR)**: プロセスのアドレス空間のレイアウトをランダム化します。これにより、攻撃者が特定のメモリ位置を予測してジャンプするのを困難にします。
* **Memory Protection (mprotect)**: `mprotect()`システムコールを悪用して、実行時にメモリ領域の実行権限を変更する攻撃を防ぎます。
* **Randomized Executable (RANDEXEC)**: 実行ファイルのロードアドレスをランダム化します。
* **Emulated Trampolines (EMUTRAMP)**: 特定の種類のジャンプ命令(特にスタック上のコードへのジャンプ)をエミュレートし、不正な実行を防ぎます。
PAXは、これらの機能をカーネルレベルで強制することで、アプリケーションの脆弱性が悪用された場合でも、攻撃の成功を困難にする「深層防御」を提供します。
### 4. `PT_PAX_FLAGS`
`PT_PAX_FLAGS`は、PAXによって導入されたカスタムのプログラムヘッダタイプです。このヘッダは、ELF実行ファイルがPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるためのフラグを含みます。具体的には、実行ファイルが特定のPAX機能を無効にしたい場合や、特定の挙動を期待する場合にこのフラグを使用します。
`PT_PAX_FLAGS`の`p_flags`フィールドには、PAXの様々なセキュリティ機能の有効/無効を制御するビットフラグが設定されます。例えば、`mprotect`、`randexec`、`emutramp`などの機能を個別に制御できます。
## 技術的詳細
このコミットは、Go言語のリンカ`cmd/5l`が生成するELFファイルに`PT_PAX_FLAGS`プログラムヘッダを追加することで、PAXが有効なシステム上でのGoバイナリの挙動を改善します。
具体的には、`src/cmd/5l/asm.c`ファイル内の`asmb`関数(アセンブリコードを生成し、ELFヘッダを構築する部分)に以下の変更が加えられています。
1. **新しいプログラムヘッダの作成**: `newElfPhdr()`関数を呼び出して、新しいELFプログラムヘッダ構造体を作成します。
2. **タイプの設定**: 作成したプログラムヘッダの`type`フィールドを`PT_PAX_FLAGS`に設定します。これは、このヘッダがPAX関連のフラグを保持することを示します。
3. **フラグの設定**: `flags`フィールドに`0x2a00`という値を設定します。この値は、PAXの特定のセキュリティ機能を無効にするためのビットマスクです。コミットメッセージのコメントには「mprotect, randexec, emutramp disabled」と書かれており、このフラグがこれらの機能を無効にすることを示唆しています。
* `0x2a00`という値は、バイナリ形式で`0010 1010 0000 0000`となります。PAXのフラグは通常、特定のビットがセットされているかどうかで機能の有効/無効を判断します。この値が具体的にどのPAX機能を無効にするかは、PAXのソースコードやドキュメントを参照する必要がありますが、コメントにある通り、`mprotect`、`randexec`、`emutramp`に関連するビットがセットされていると考えられます。GoのランタイムがこれらのPAX機能と競合する可能性があったり、特定のパフォーマンス上の理由から、これらの機能を無効にすることが選択された可能性があります。
4. **アライメントの設定**: `align`フィールドを`4`に設定します。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされることを示します。
この変更により、Go言語でビルドされた実行ファイルは、PAXが有効なシステムでロードされる際に、カーネルに対して明示的にこれらのPAX機能の挙動を伝えることができるようになります。これにより、Goランタイムの特定の動作(例えば、JITコンパイルや動的なメモリ領域の実行権限変更など)がPAXの厳格なセキュリティポリシーと衝突するのを防ぎ、安定した動作を保証しつつ、必要に応じて他のPAXセキュリティ機能(ASLRなど)の恩恵を受けることが可能になります。
## コアとなるコードの変更箇所
変更は`src/cmd/5l/asm.c`ファイルに集中しており、具体的には以下の5行が追加されています。
```diff
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
## コアとなるコードの解説
追加されたコードは、ELF実行ファイルのプログラムヘッダテーブルに新しいエントリを追加する処理です。
* `ph = newElfPhdr();`
* `newElfPhdr()`関数は、新しいELFプログラムヘッダ構造体をヒープ上に割り当て、そのポインタを返します。この構造体は、ELFファイルがメモリにロードされる際のセグメントの特性を定義するために使用されます。
* `ph->type = PT_PAX_FLAGS;`
* 新しく作成されたプログラムヘッダの`type`フィールドに`PT_PAX_FLAGS`を代入しています。これは、このプログラムヘッダがPAXセキュリティ機能に関連するフラグを保持することを示す、PAXによって定義されたカスタムタイプです。
* `ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled`
* プログラムヘッダの`flags`フィールドに`0x2a00`という16進数値を設定しています。この値は、PAXカーネルが解釈するビットマスクであり、特定のPAXセキュリティ機能を無効にするためのものです。コメントにある通り、このフラグは`mprotect`、`randexec`、`emutramp`といったPAXのセキュリティ機能を無効にする効果があります。これは、Goランタイムがこれらの機能と競合する可能性があったり、特定の動作のためにこれらの機能を一時的に緩和する必要がある場合に設定されます。
* `ph->align = 4;`
* プログラムヘッダの`align`フィールドに`4`を設定しています。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされるべきであることを示します。アライメントは、プロセッサがメモリにアクセスする際の効率や、特定のハードウェア要件を満たすために重要です。
これらの行は、Go言語のリンカがARMアーキテクチャ向けの実行ファイルを生成する際に、PAX対応のカーネルがそのバイナリを適切に処理できるように、必要なセキュリティメタデータをELFヘッダに埋め込む役割を果たします。
## 関連リンク
* [https://golang.org/cl/6453092](https://golang.org/cl/6453092) - このコミットに対応するGoのコードレビュー(Change List)ページ。
## 参考にした情報源リンク
* **ELF (Executable and Linkable Format)**:
* [Wikipedia: Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
* [Linux man page: elf(5)](https://man7.org/linux/man-pages/man5/elf.5.html)
* **PAX (Program Analysis eXecutor)**:
* [PaX Project Homepage](https://pax.grsecurity.net/)
* [Wikipedia: PaX](https://en.wikipedia.org/wiki/PaX)
* **PT_PAX_FLAGS**:
* PAXのドキュメントやソースコード(特に`elf.h`や関連するカーネルコード)で詳細が定義されています。一般的な情報源では直接的な説明が少ないため、PAXプロジェクトの公式リソースを参照することが最も正確な情報を得る方法です。
* [grsecurity/PaX documentation (古い情報を含む可能性あり)](https://grsecurity.net/pax.php)
* [Linuxカーネルのソースコード内の関連定義 (例: `include/uapi/linux/elf.h`や`arch/x86/include/asm/elf.h`など)](https://elixir.bootlin.com/linux/latest/source) - `PT_PAX_FLAGS`の定義は、PAXパッチが適用されたカーネルのヘッダファイルに存在します。
# [インデックス 13609] ファイルの概要
このコミットは、Go言語のリンカである`cmd/5l`(ARMアーキテクチャ向け)に、ELFヘッダに`PT_PAX_FLAGS`という新しいプログラムヘッダを追加する変更を導入しています。これにより、PAX(Program Analysis eXecutor)セキュリティ機能が有効なARMカーネル環境において、生成される実行ファイルのセキュリティ属性を適切に設定できるようになります。
## コミット
cmd/5l: add PT_PAX_FLAGS ELF header Although I don't use PAX enabled ARM kernels, PAX does have support for ARM, so we're better off add PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6453092
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/af92b29fe63bd68b3892f6773b3da5896db52e6e](https://github.com/golang/go/commit/af92b29fe63bd68b3892f6773b3da5896db52e6e)
## 元コミット内容
commit af92b29fe63bd68b3892f6773b3da5896db52e6e Author: Shenghou Ma minux.ma@gmail.com Date: Thu Aug 9 08:47:43 2012 +0800
cmd/5l: add PT_PAX_FLAGS ELF header
Although I don't use PAX enabled ARM kernels, PAX
does have support for ARM, so we're better off add
PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6453092
src/cmd/5l/asm.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 3e51ece462..e39fcc9641 100644 --- a/src/cmd/5l/asm.c +++ b/cmd/5l/asm.c @@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
変更の背景
この変更の背景には、Go言語で生成される実行ファイルが、PAX(Program Analysis eXecutor)セキュリティ機能が有効なLinuxカーネル環境、特にARMアーキテクチャ上で適切に動作し、かつセキュリティ上の恩恵を受けられるようにするという意図があります。
コミットメッセージには「Although I don't use PAX enabled ARM kernels, PAX does have support for ARM, so we're better off add PT_PAX_FLAGS now in case people use PAX kernels.」と明記されています。これは、コミットの作者自身はPAXが有効なARMカーネルを使用していないものの、PAXがARMをサポートしているため、将来的にPAXカーネルを使用するユーザーのために、現時点でPT_PAX_FLAGS
を追加しておくことが望ましいという判断を示しています。
PAXは、様々なメモリ保護メカニズムを実装することで、バッファオーバーフローなどの一般的な脆弱性を悪用した攻撃を防ぐことを目的としたLinuxカーネルのパッチセットです。これらのセキュリティ機能は、実行ファイルが特定のセキュリティ属性を持つことを期待します。PT_PAX_FLAGS
プログラムヘッダは、実行ファイルがこれらのPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるための標準的な方法です。このヘッダを追加することで、Go言語でビルドされたバイナリがPAX環境下で予期せぬ挙動をすることなく、またPAXが提供するセキュリティ保護を最大限に活用できるようになります。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。
1. ELF (Executable and Linkable Format)
ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている実行可能ファイル、オブジェクトファイル、共有ライブラリ、およびコアダンプファイルの標準フォーマットです。ELFファイルは、プログラムの実行に必要なすべての情報(コード、データ、シンボルテーブル、再配置情報など)を構造化された形式で格納します。
ELFファイルは主に以下のセクションで構成されます。
- ELFヘッダ: ファイルのタイプ(実行可能ファイル、オブジェクトファイルなど)、アーキテクチャ、エントリポイントアドレスなど、ファイル全体の基本的な情報を含みます。
- プログラムヘッダテーブル (Program Header Table): 実行可能ファイルや共有ライブラリにのみ存在し、プログラムのロード方法を記述します。各エントリ(プログラムヘッダ)は、メモリセグメントのタイプ、ファイル内のオフセット、メモリ上のアドレス、サイズ、アクセス権限(読み取り、書き込み、実行)などを定義します。
- セクションヘッダテーブル (Section Header Table): オブジェクトファイルや共有ライブラリに存在し、ファイル内の各セクション(.text, .data, .bssなど)の属性を記述します。
- セクション: 実際のコードやデータが格納される領域です。
2. プログラムヘッダ (Program Header) とそのタイプ
プログラムヘッダは、ELFファイルがメモリにロードされる方法をカーネルに指示する構造体です。各プログラムヘッダは、p_type
フィールドによってその種類が定義されます。一般的なタイプには以下のようなものがあります。
PT_LOAD
: メモリにロードされるセグメントを記述します。実行可能コードや初期化されたデータなどがこれに該当します。PT_INTERP
: プログラムインタプリタ(例:/lib/ld-linux.so.2
)のパスを記述します。PT_DYNAMIC
: 動的リンク情報を含むセグメントを記述します。PT_NOTE
: ノートセクション(特別な情報)を記述します。
3. PAX (Program Analysis eXecutor)
PAXは、Linuxカーネルのセキュリティ強化パッチセットであり、様々なメモリ保護技術を実装して、一般的なソフトウェアの脆弱性(特にメモリ破損の脆弱性)を悪用した攻撃を防ぐことを目的としています。PAXが提供する主なセキュリティ機能には以下のようなものがあります。
- Non-Executable Pages (NX/DEP): データセグメントからのコード実行を防ぎます。これにより、スタックやヒープに注入されたシェルコードの実行を困難にします。
- Address Space Layout Randomization (ASLR): プロセスのアドレス空間のレイアウトをランダム化します。これにより、攻撃者が特定のメモリ位置を予測してジャンプするのを困難にします。
- Memory Protection (mprotect):
mprotect()
システムコールを悪用して、実行時にメモリ領域の実行権限を変更する攻撃を防ぎます。 - Randomized Executable (RANDEXEC): 実行ファイルのロードアドレスをランダム化します。
- Emulated Trampolines (EMUTRAMP): 特定の種類のジャンプ命令(特にスタック上のコードへのジャンプ)をエミュレートし、不正な実行を防ぎます。
PAXは、これらの機能をカーネルレベルで強制することで、アプリケーションの脆弱性が悪用された場合でも、攻撃の成功を困難にする「深層防御」を提供します。
4. PT_PAX_FLAGS
PT_PAX_FLAGS
は、PAXによって導入されたカスタムのプログラムヘッダタイプです。このヘッダは、ELF実行ファイルがPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるためのフラグを含みます。具体的には、実行ファイルが特定のPAX機能を無効にしたい場合や、特定の挙動を期待する場合にこのフラグを使用します。
PT_PAX_FLAGS
のp_flags
フィールドには、PAXの様々なセキュリティ機能の有効/無効を制御するビットフラグが設定されます。例えば、mprotect
、randexec
、emutramp
などの機能を個別に制御できます。
技術的詳細
このコミットは、Go言語のリンカcmd/5l
が生成するELFファイルにPT_PAX_FLAGS
プログラムヘッダを追加することで、PAXが有効なシステム上でのGoバイナリの挙動を改善します。
具体的には、src/cmd/5l/asm.c
ファイル内のasmb
関数(アセンブリコードを生成し、ELFヘッダを構築する部分)に以下の変更が加えられています。
- 新しいプログラムヘッダの作成:
newElfPhdr()
関数を呼び出して、新しいELFプログラムヘッダ構造体を作成します。 - タイプの設定: 作成したプログラムヘッダの
type
フィールドをPT_PAX_FLAGS
に設定します。これは、このヘッダがPAX関連のフラグを保持することを示します。 - フラグの設定:
flags
フィールドに0x2a00
という値を設定します。この値は、PAXの特定のセキュリティ機能を無効にするためのビットマスクです。コミットメッセージのコメントには「mprotect, randexec, emutramp disabled」と書かれており、このフラグがこれらの機能を無効にすることを示唆しています。0x2a00
という値は、バイナリ形式で0010 1010 0000 0000
となります。PAXのフラグは通常、特定のビットがセットされているかどうかで機能の有効/無効を判断します。この値が具体的にどのPAX機能を無効にするかは、PAXのソースコードやドキュメントを参照する必要がありますが、コメントにある通り、mprotect
、randexec
、emutramp
に関連するビットがセットされていると考えられます。GoのランタイムがこれらのPAX機能と競合する可能性があったり、特定のパフォーマンス上の理由から、これらの機能を無効にすることが選択された可能性があります。
- アライメントの設定:
align
フィールドを4
に設定します。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされることを示します。
この変更により、Go言語でビルドされた実行ファイルは、PAXが有効なシステムでロードされる際に、カーネルに対して明示的にこれらのPAX機能の挙動を伝えることができるようになります。これにより、Goランタイムの特定の動作(例えば、JITコンパイルや動的なメモリ領域の実行権限変更など)がPAXの厳格なセキュリティポリシーと衝突するのを防ぎ、安定した動作を保証しつつ、必要に応じて他のPAXセキュリティ機能(ASLRなど)の恩恵を受けることが可能になります。
コアとなるコードの変更箇所
変更はsrc/cmd/5l/asm.c
ファイルに集中しており、具体的には以下の5行が追加されています。
--- a/src/cmd/5l/asm.c
+++ b/cmd/5l/asm.c
@@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
## コアとなるコードの解説
追加されたコードは、ELF実行ファイルのプログラムヘッダテーブルに新しいエントリを追加する処理です。
* `ph = newElfPhdr();`
* `newElfPhdr()`関数は、新しいELFプログラムヘッダ構造体をヒープ上に割り当て、そのポインタを返します。この構造体は、ELFファイルがメモリにロードされる際のセグメントの特性を定義するために使用されます。
* `ph->type = PT_PAX_FLAGS;`
* 新しく作成されたプログラムヘッダの`type`フィールドに`PT_PAX_FLAGS`を代入しています。これは、このプログラムヘッダがPAXセキュリティ機能に関連するフラグを保持することを示す、PAXによって定義されたカスタムタイプです。
* `ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled`
* プログラムヘッダの`flags`フィールドに`0x2a00`という16進数値を設定しています。この値は、PAXカーネルが解釈するビットマスクであり、特定のPAXセキュリティ機能を無効にするためのものです。コメントにある通り、このフラグは`mprotect`、`randexec`、`emutramp`といったPAXのセキュリティ機能を無効にする効果があります。これは、Goランタイムがこれらの機能と競合する可能性があったり、特定の動作のためにこれらの機能を一時的に緩和する必要がある場合に設定されます。
* `ph->align = 4;`
* プログラムヘッダの`align`フィールドに`4`を設定しています。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされるべきであることを示します。アライメントは、プロセッサがメモリにアクセスする際の効率や、特定のハードウェア要件を満たすために重要です。
これらの行は、Go言語のリンカがARMアーキテクチャ向けの実行ファイルを生成する際に、PAX対応のカーネルがそのバイナリを適切に処理できるように、必要なセキュリティメタデータをELFヘッダに埋め込む役割を果たします。
## 関連リンク
* [https://golang.org/cl/6453092](https://golang.org/cl/6453092) - このコミットに対応するGoのコードレビュー(Change List)ページ。
## 参考にした情報源リンク
* **ELF (Executable and Linkable Format)**:
* [Wikipedia: Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
* [Linux man page: elf(5)](https://man7.org/linux/man-pages/man5/elf.5.html)
* **PAX (Program Analysis eXecutor)**:
* [PaX Project Homepage](https://pax.grsecurity.net/)
* [Wikipedia: PaX](https://en.wikipedia.org/wiki/PaX)
* **PT_PAX_FLAGS**:
* [wikibooks.org: PaX/PT_PAX_FLAGS](https://en.wikibooks.org/wiki/PaX/PT_PAX_FLAGS)
* [grsecurity.net: PaX documentation](https://grsecurity.net/pax.php)
* [openssf.org: ELF Program Headers](https://www.openssf.org/blog/2023/03/29/elf-program-headers/)
* Linuxカーネルのソースコード内の関連定義 (例: `include/uapi/linux/elf.h`や`arch/x86/include/asm/elf.h`など) - `PT_PAX_FLAGS`の定義は、PAXパッチが適用されたカーネルのヘッダファイルに存在します。
# [インデックス 13609] ファイルの概要
このコミットは、Go言語のリンカである`cmd/5l`(ARMアーキテクチャ向け)に、ELFヘッダに`PT_PAX_FLAGS`という新しいプログラムヘッダを追加する変更を導入しています。これにより、PAX(Program Analysis eXecutor)セキュリティ機能が有効なARMカーネル環境において、生成される実行ファイルのセキュリティ属性を適切に設定できるようになります。
## コミット
cmd/5l: add PT_PAX_FLAGS ELF header Although I don't use PAX enabled ARM kernels, PAX does have support for ARM, so we're better off add PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6453092
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/af92b29fe63bd68b3892f6773b3da5896db52e6e](https://github.com/golang/go/commit/af92b29fe63bd68b3892f6773b3da5896db52e6e)
## 元コミット内容
commit af92b29fe63bd68b3892f6773b3da5896db52e6e Author: Shenghou Ma minux.ma@gmail.com Date: Thu Aug 9 08:47:43 2012 +0800
cmd/5l: add PT_PAX_FLAGS ELF header
Although I don't use PAX enabled ARM kernels, PAX
does have support for ARM, so we're better off add
PT_PAX_FLAGS now in case people use PAX kernels.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6453092
src/cmd/5l/asm.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 3e51ece462..e39fcc9641 100644 --- a/src/cmd/5l/asm.c +++ b/cmd/5l/asm.c @@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
変更の背景
この変更の背景には、Go言語で生成される実行ファイルが、PAX(Program Analysis eXecutor)セキュリティ機能が有効なLinuxカーネル環境、特にARMアーキテクチャ上で適切に動作し、かつセキュリティ上の恩恵を受けられるようにするという意図があります。
コミットメッセージには「Although I don't use PAX enabled ARM kernels, PAX does have support for ARM, so we're better off add PT_PAX_FLAGS now in case people use PAX kernels.」と明記されています。これは、コミットの作者自身はPAXが有効なARMカーネルを使用していないものの、PAXがARMをサポートしているため、将来的にPAXカーネルを使用するユーザーのために、現時点でPT_PAX_FLAGS
を追加しておくことが望ましいという判断を示しています。
PAXは、様々なメモリ保護メカニズムを実装することで、バッファオーバーフローなどの一般的な脆弱性を悪用した攻撃を防ぐことを目的としたLinuxカーネルのパッチセットです。これらのセキュリティ機能は、実行ファイルが特定のセキュリティ属性を持つことを期待します。PT_PAX_FLAGS
プログラムヘッダは、実行ファイルがこれらのPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるための標準的な方法です。このヘッダを追加することで、Go言語でビルドされたバイナリがPAX環境下で予期せぬ挙動をすることなく、またPAXが提供するセキュリティ保護を最大限に活用できるようになります。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。
1. ELF (Executable and Linkable Format)
ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている実行可能ファイル、オブジェクトファイル、共有ライブラリ、およびコアダンプファイルの標準フォーマットです。ELFファイルは、プログラムの実行に必要なすべての情報(コード、データ、シンボルテーブル、再配置情報など)を構造化された形式で格納します。
ELFファイルは主に以下のセクションで構成されます。
- ELFヘッダ: ファイルのタイプ(実行可能ファイル、オブジェクトファイルなど)、アーキテクチャ、エントリポイントアドレスなど、ファイル全体の基本的な情報を含みます。
- プログラムヘッダテーブル (Program Header Table): 実行可能ファイルや共有ライブラリにのみ存在し、プログラムのロード方法を記述します。各エントリ(プログラムヘッダ)は、メモリセグメントのタイプ、ファイル内のオフセット、メモリ上のアドレス、サイズ、アクセス権限(読み取り、書き込み、実行)などを定義します。
- セクションヘッダテーブル (Section Header Table): オブジェクトファイルや共有ライブラリに存在し、ファイル内の各セクション(.text, .data, .bssなど)の属性を記述します。
- セクション: 実際のコードやデータが格納される領域です。
2. プログラムヘッダ (Program Header) とそのタイプ
プログラムヘッダは、ELFファイルがメモリにロードされる方法をカーネルに指示する構造体です。各プログラムヘッダは、p_type
フィールドによってその種類が定義されます。一般的なタイプには以下のようなものがあります。
PT_LOAD
: メモリにロードされるセグメントを記述します。実行可能コードや初期化されたデータなどがこれに該当します。PT_INTERP
: プログラムインタプリタ(例:/lib/ld-linux.so.2
)のパスを記述します。PT_DYNAMIC
: 動的リンク情報を含むセグメントを記述します。PT_NOTE
: ノートセクション(特別な情報)を記述します。
3. PAX (Program Analysis eXecutor)
PAXは、Linuxカーネルのセキュリティ強化パッチセットであり、様々なメモリ保護技術を実装して、一般的なソフトウェアの脆弱性(特にメモリ破損の脆弱性)を悪用した攻撃を防ぐことを目的としています。PAXが提供する主なセキュリティ機能には以下のようなものがあります。
- Non-Executable Pages (NX/DEP): データセグメントからのコード実行を防ぎます。これにより、スタックやヒープに注入されたシェルコードの実行を困難にします。
- Address Space Layout Randomization (ASLR): プロセスのアドレス空間のレイアウトをランダム化します。これにより、攻撃者が特定のメモリ位置を予測してジャンプするのを困難にします。
- Memory Protection (mprotect):
mprotect()
システムコールを悪用して、実行時にメモリ領域の実行権限を変更する攻撃を防ぎます。 - Randomized Executable (RANDEXEC): 実行ファイルのロードアドレスをランダム化します。
- Emulated Trampolines (EMUTRAMP): 特定の種類のジャンプ命令(特にスタック上のコードへのジャンプ)をエミュレートし、不正な実行を防ぎます。
PAXは、これらの機能をカーネルレベルで強制することで、アプリケーションの脆弱性が悪用された場合でも、攻撃の成功を困難にする「深層防御」を提供します。
4. PT_PAX_FLAGS
PT_PAX_FLAGS
は、PAXによって導入されたカスタムのプログラムヘッダタイプです。このヘッダは、ELF実行ファイルがPAXセキュリティ機能とどのように相互作用するかをカーネルに伝えるためのフラグを含みます。具体的には、実行ファイルが特定のPAX機能を無効にしたい場合や、特定の挙動を期待する場合にこのフラグを使用します。
PT_PAX_FLAGS
のp_flags
フィールドには、PAXの様々なセキュリティ機能の有効/無効を制御するビットフラグが設定されます。例えば、mprotect
、randexec
、emutramp
などの機能を個別に制御できます。
技術的詳細
このコミットは、Go言語のリンカcmd/5l
が生成するELFファイルにPT_PAX_FLAGS
プログラムヘッダを追加することで、PAXが有効なシステム上でのGoバイナリの挙動を改善します。
具体的には、src/cmd/5l/asm.c
ファイル内のasmb
関数(アセンブリコードを生成し、ELFヘッダを構築する部分)に以下の変更が加えられています。
- 新しいプログラムヘッダの作成:
newElfPhdr()
関数を呼び出して、新しいELFプログラムヘッダ構造体を作成します。 - タイプの設定: 作成したプログラムヘッダの
type
フィールドをPT_PAX_FLAGS
に設定します。これは、このヘッダがPAX関連のフラグを保持することを示します。 - フラグの設定:
flags
フィールドに0x2a00
という値を設定します。この値は、PAXの特定のセキュリティ機能を無効にするためのビットマスクです。コミットメッセージのコメントには「mprotect, randexec, emutramp disabled」と書かれており、このフラグがこれらの機能を無効にすることを示唆しています。0x2a00
という値は、バイナリ形式で0010 1010 0000 0000
となります。PAXのフラグは通常、特定のビットがセットされているかどうかで機能の有効/無効を判断します。この値が具体的にどのPAX機能を無効にするかは、PAXのソースコードやドキュメントを参照する必要がありますが、コメントにある通り、mprotect
、randexec
、emutramp
に関連するビットがセットされていると考えられます。GoのランタイムがこれらのPAX機能と競合する可能性があったり、特定のパフォーマンス上の理由から、これらの機能を無効にすることが選択された可能性があります。
- アライメントの設定:
align
フィールドを4
に設定します。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされることを示します。
この変更により、Go言語でビルドされた実行ファイルは、PAXが有効なシステムでロードされる際に、カーネルに対して明示的にこれらのPAX機能の挙動を伝えることができるようになります。これにより、Goランタイムの特定の動作(例えば、JITコンパイルや動的なメモリ領域の実行権限変更など)がPAXの厳格なセキュリティポリシーと衝突するのを防ぎ、安定した動作を保証しつつ、必要に応じて他のPAXセキュリティ機能(ASLRなど)の恩恵を受けることが可能になります。
コアとなるコードの変更箇所
変更はsrc/cmd/5l/asm.c
ファイルに集中しており、具体的には以下の5行が追加されています。
--- a/src/cmd/5l/asm.c
+++ b/cmd/5l/asm.c
@@ -963,6 +963,11 @@ asmb(void)\n \t\tph->flags = PF_W+PF_R;\n \t\tph->align = 4;\n \n+\t\tph = newElfPhdr();\n+\t\tph->type = PT_PAX_FLAGS;\n+\t\tph->flags = 0x2a00; // mprotect, randexec, emutramp disabled\n+\t\tph->align = 4;\n+\n \t\tsh = newElfShstrtab(elfstr[ElfStrShstrtab]);\n \t\tsh->type = SHT_STRTAB;\n \t\tsh->addralign = 1;\n```
## コアとなるコードの解説
追加されたコードは、ELF実行ファイルのプログラムヘッダテーブルに新しいエントリを追加する処理です。
* `ph = newElfPhdr();`
* `newElfPhdr()`関数は、新しいELFプログラムヘッダ構造体をヒープ上に割り当て、そのポインタを返します。この構造体は、ELFファイルがメモリにロードされる際のセグメントの特性を定義するために使用されます。
* `ph->type = PT_PAX_FLAGS;`
* 新しく作成されたプログラムヘッダの`type`フィールドに`PT_PAX_FLAGS`を代入しています。これは、このプログラムヘッダがPAXセキュリティ機能に関連するフラグを保持することを示す、PAXによって定義されたカスタムタイプです。
* `ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled`
* プログラムヘッダの`flags`フィールドに`0x2a00`という16進数値を設定しています。この値は、PAXカーネルが解釈するビットマスクであり、特定のPAXセキュリティ機能を無効にするためのものです。コメントにある通り、このフラグは`mprotect`、`randexec`、`emutramp`といったPAXのセキュリティ機能を無効にする効果があります。これは、Goランタイムがこれらの機能と競合する可能性があったり、特定の動作のためにこれらの機能を一時的に緩和する必要がある場合に設定されます。
* `ph->align = 4;`
* プログラムヘッダの`align`フィールドに`4`を設定しています。これは、このプログラムヘッダがメモリ上で4バイト境界にアラインされるべきであることを示します。アライメントは、プロセッサがメモリにアクセスする際の効率や、特定のハードウェア要件を満たすために重要です。
これらの行は、Go言語のリンカがARMアーキテクチャ向けの実行ファイルを生成する際に、PAX対応のカーネルがそのバイナリを適切に処理できるように、必要なセキュリティメタデータをELFヘッダに埋め込む役割を果たします。
## 関連リンク
* [https://golang.org/cl/6453092](https://golang.org/cl/6453092) - このコミットに対応するGoのコードレビュー(Change List)ページ。
## 参考にした情報源リンク
* **ELF (Executable and Linkable Format)**:
* [Wikipedia: Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
* [Linux man page: elf(5)](https://man7.org/linux/man-pages/man5/elf.5.html)
* **PAX (Program Analysis eXecutor)**:
* [PaX Project Homepage](https://pax.grsecurity.net/)
* [Wikipedia: PaX](https://en.wikipedia.org/wiki/PaX)
* **PT_PAX_FLAGS**:
* [wikibooks.org: PaX/PT_PAX_FLAGS](https://en.wikibooks.org/wiki/PaX/PT_PAX_FLAGS)
* [grsecurity.net: PaX documentation](https://grsecurity.net/pax.php)
* [openssf.org: ELF Program Headers](https://www.openssf.org/blog/2023/03/29/elf-program-headers/)
* Linuxカーネルのソースコード内の関連定義 (例: `include/uapi/linux/elf.h`や`arch/x86/include/asm/elf.h`など) - `PT_PAX_FLAGS`の定義は、PAXパッチが適用されたカーネルのヘッダファイルに存在します。