Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16264] ファイルの概要

このコミットは、src/pkg/runtime/cgo/gcc_arm.S ファイルに対する変更です。具体的には、ARMアーキテクチャ向けのCGO(C言語との相互運用)ランタイムビルドにおける問題を修正しています。

コミット

commit 988236ba86c8cb7ceb027cd2eaf091b4363f20e2
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri May 3 17:15:43 2013 +0800

    runtime/cgo: fix build for ARM
    
    TBR=iant
    CC=golang-dev
    https://golang.org/cl/9048048

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/988236ba86c8cb7ceb027cd2eaf091b4363f20e2

元コミット内容

runtime/cgo: fix build for ARM

変更の背景

このコミットは、Go言語のランタイムにおけるCGO(C言語との相互運用)機能がARMアーキテクチャでビルドされる際に発生していた問題を修正するために行われました。具体的には、アセンブリコード内でELFセクションを定義する際の構文が、ARMアーキテクチャのGNUアセンブラ(as)の特定のバージョンで正しく解釈されないことが原因でした。

ELF(Executable and Linkable Format)ファイルにおいて、.note.GNU-stackセクションは、スタックの実行可能性に関する情報をリンカに伝えるために使用されます。非実行可能なスタックは、バッファオーバーフロー攻撃など、スタックに悪意のあるコードを注入して実行しようとする攻撃を防ぐための重要なセキュリティ対策です。このセクションは通常、progbitsタイプとして宣言されます。

問題は、GNUアセンブラにおいてセクションタイプを指定する際に、一般的な構文である@progbitsが、ARMアーキテクチャでは@がコメントの開始文字として解釈されてしまうことにありました。これにより、セクションタイプが正しく認識されず、ビルドエラーや予期せぬ動作を引き起こす可能性がありました。このコミットは、ARM環境でのビルドを成功させるために、この構文の差異を吸収することを目的としています。

前提知識の解説

ELF (Executable and Linkable Format)

ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている、実行可能ファイル、オブジェクトコード、共有ライブラリ、コアダンプなどの標準ファイル形式です。柔軟性が高く、ARMのような様々なアーキテクチャに対応しています。

.note.GNU-stack セクション

ELFファイル内の特別なセクションで、GNUツール(GNUアセンブラ as やGNUリンカ ld など)によって、スタックの実行可能性に関する情報を伝達するために使用されます。このセクションが存在し、適切にマークされている場合(例えば、実行可能フラグなし)、リンカに対してスタックが実行可能であってはならないことを指示します。これは、セキュリティ上の脆弱性(例:バッファオーバーフローによるコード実行)を防ぐための重要なセキュリティ機能です。

progbits

ELFファイルにおけるセクションタイプ(SHT_PROGBITS)の一つです。これは、セクションが「プログラムのビット」またはプログラムの一部を形成する実際のデータを含んでいることを意味します。これには、実行可能コード、初期化されたデータ、およびプログラムによって明示的に定義されたその他の情報が含まれます。.note.GNU-stackの文脈では、このセクションはプログラム自体の実行可能コードを含んでいませんが、リンカのためのメタデータを含んでいるため、通常progbitsタイプとして扱われます。

ARMアセンブリ

ARMアーキテクチャ向けに書かれたアセンブリ言語コードを指します。ARMは、RISC(Reduced Instruction Set Computer)アーキテクチャのファミリーであり、モバイルデバイス、組み込みシステム、そして近年ではサーバーやデスクトップでも広く使用されています。ARMアセンブリでは、.sectionのようなディレクティブを使用して、出力オブジェクトファイル内のセクションを定義します。

@progbits%progbits

これらは、GNUアセンブラ(as)を使用してアセンブリ言語でセクションタイプを指定する方法です。

  • @progbits: 一般的に、.sectionディレクティブでセクションタイプを指定するために使用される構文です。
  • %progbits: ARMのような一部のターゲットでは、@文字がコメントの開始として解釈される可能性があるため、代わりに%文字がセクションタイプを指定するために使用されます。したがって、ARMアセンブリでは、.section .note.GNU-stack,\"\",%progbitsのように記述することで、.note.GNU-stackセクションをprogbitsタイプとして宣言し、それがデータ(リンカのためのメタデータであっても)を含み、実行可能ではないことを示します。

このコミットは、ARM環境におけるGNUアセンブラの挙動の違いに対応するために、@progbits%progbitsに変更しています。

技術的詳細

このコミットの技術的な核心は、GNUアセンブラ(as)が異なるアーキテクチャ(特にARM)でセクション属性をどのように解釈するかの違いにあります。

ELFファイルでは、.sectionディレクティブを使用して新しいセクションを定義し、その属性を指定します。一般的な構文は以下のようになります。

.section name, "flags", @type

ここで、typeはセクションの目的を示すもので、progbitsは「プログラムのデータ」を意味します。

しかし、ARMアーキテクチャ向けのGNUアセンブラでは、@記号がコメントの開始文字として扱われる場合があります。このため、.section .note.GNU-stack,"",@progbitsという記述は、@progbitsの部分がコメントとして無視され、セクションタイプが正しく設定されないという問題が発生していました。

この問題を解決するため、ARMアセンブラではセクションタイプを指定する際に%記号を使用する慣習があります。つまり、%progbitsと記述することで、progbitsがセクションタイプとして正しく認識されるようになります。

このコミットは、src/pkg/runtime/cgo/gcc_arm.Sファイル内の.note.GNU-stackセクションの定義を、@progbitsから%progbitsに変更することで、ARM環境でのビルドが正しく行われるように修正しています。これにより、生成されるELFファイルが意図した通りに.note.GNU-stackセクションを持ち、スタックの非実行可能性がリンカに正しく伝達されるようになります。これは、セキュリティとビルドの安定性の両面で重要な修正です。

コアとなるコードの変更箇所

--- a/src/pkg/runtime/cgo/gcc_arm.S
+++ b/src/pkg/runtime/cgo/gcc_arm.S
@@ -35,5 +35,5 @@ EXT(__stack_chk_fail_local):
 	b 1b
 
 #ifdef __ELF__
-.section .note.GNU-stack,"",@progbits
+.section .note.GNU-stack,"",%progbits
 #endif

コアとなるコードの解説

変更された行は、src/pkg/runtime/cgo/gcc_arm.Sファイル内の以下の部分です。

#ifdef __ELF__
.section .note.GNU-stack,"",@progbits
#endif

このコードは、__ELF__が定義されている場合(つまり、ELF形式のバイナリを生成する場合)に、.note.GNU-stackという名前のセクションを定義しています。このセクションは、スタックの実行可能性に関する情報をリンカに伝えるためのものです。

元のコードでは、セクションタイプとして@progbitsが指定されていました。しかし、前述の通り、ARMアーキテクチャのGNUアセンブラでは@がコメント文字として解釈されるため、この指定が正しく機能しませんでした。

修正後のコードは以下のようになります。

#ifdef __ELF__
.section .note.GNU-stack,"",%progbits
#endif

@progbits%progbitsに変更されています。この変更により、ARMアーキテクチャのGNUアセンブラは%progbitsを正しくセクションタイプとして認識し、.note.GNU-stackセクションが意図した通りにELFファイルに組み込まれるようになります。これにより、GoランタイムのCGO機能がARM環境で正しくビルドされ、セキュリティ上の要件も満たされるようになります。

関連リンク

参考にした情報源リンク