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

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

このコミットは、GoランタイムにおけるNative Client (NaCl) 環境向けの小規模な修正を導入します。具体的には、mem_nacl.cSysFault関数を追加し、env_posix.cのビルドタグにnaclを追加することで、Native Client環境でのGoプログラムの安定性と互換性を向上させています。

コミット

runtime: small Native Client fixes

mem_nacl.c: add SysFault
env_posix.c: add nacl to build tag, from CL 15790043

LGTM=remyoudompheng, iant
R=rsc, remyoudompheng, iant
CC=golang-codereviews
https://golang.org/cl/72780043

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

https://github.com/golang/go/commit/9ab4d1d6b3d90cc4837edae0b5857dae33e79ebd

元コミット内容

runtime: small Native Client fixes

mem_nacl.c: add SysFault
env_posix.c: add nacl to build tag, from CL 15790043

LGTM=remyoudompheng, iant
R=rsc, remyoudompheng, iant
CC=golang-codereviews
https://golang.org/cl/72780043

変更の背景

この変更は、GoプログラムがGoogle Native Client (NaCl) 環境で正しく動作するために必要な修正です。Native Clientは、ウェブブラウザ内でネイティブコードを安全に実行するためのサンドボックス技術です。Goランタイムは、様々なオペレーティングシステムやアーキテクチャに対応するために、プラットフォーム固有のコードを含んでいます。

SysFault関数の追加は、Goランタイムがメモリ保護違反(セグメンテーションフォールトなど)を適切に処理するために必要です。NaCl環境では、メモリ管理や保護のメカニズムが通常のOSとは異なるため、Goランタイムがこれらの違いに適応する必要があります。SysFaultは、特定のメモリ領域をアクセス不可に設定することで、不正なメモリアクセスを検出し、プログラムのクラッシュを防ぐための重要なメカニズムを提供します。

また、env_posix.cnaclビルドタグを追加することは、このファイルがNative Client環境向けにもコンパイルされるべきであることをGoツールチェインに指示します。env_posix.cはPOSIX互換システム(Linux、macOSなど)向けの環境関連のランタイムコードを含んでおり、NaClもPOSIXライクなインターフェースを提供するため、このファイルがNaClビルドに含まれることが適切です。これにより、NaCl環境でGoプログラムがビルドされる際に、必要な環境設定が正しく適用されるようになります。

これらの変更は、GoプログラムがNaClのサンドボックス内で安全かつ効率的に実行されるための互換性と安定性を確保することを目的としています。

前提知識の解説

Goランタイム

Goランタイムは、Go言語で書かれたプログラムを実行するために必要な基盤ソフトウェアです。これには、ガベージコレクタ、スケジューラ、メモリ管理、システムコールインターフェースなどが含まれます。Goプログラムは、コンパイル時にGoランタイムとリンクされ、自己完結型のバイナリを生成します。ランタイムは、プログラムの実行中にメモリの割り当て、ゴルーチンのスケジューリング、システムリソースへのアクセスなどを管理します。

Google Native Client (NaCl)

Google Native Client (NaCl) は、ウェブブラウザ内でネイティブコード(C/C++など)を安全に実行するためのオープンソース技術です。NaClは、強力なサンドボックス環境を提供し、悪意のあるコードがシステムにアクセスしたり、ブラウザのセキュリティを侵害したりするのを防ぎます。NaClは、特定のCPUアーキテクチャ(x86、ARMなど)に依存しないポータブルな実行形式(PNaCl: Portable Native Client)も提供し、一度コンパイルすれば様々なプラットフォームで実行できることを目指しています。Go言語もNaClをターゲットとしてサポートしており、Goプログラムをウェブブラウザ内で実行できるようにします。

SysFault

SysFaultは、Goランタイムにおけるメモリ保護関連の関数の一つです。これは、特定のメモリ領域をアクセス不可(保護)に設定するために使用されます。通常、これは不正なメモリアクセスを検出したり、特定のメモリ領域が使用されていないことを保証したりするために行われます。例えば、Goのガベージコレクタがメモリを解放した後、その領域が誤ってアクセスされないようにSysFaultを使って保護することがあります。SysFaultが設定されたメモリ領域にアクセスしようとすると、オペレーティングシステムはセグメンテーションフォールトなどの例外を発生させ、Goランタイムがこれを捕捉して適切に処理することができます。

ビルドタグ (Build Tags)

Goのビルドタグ(またはビルド制約)は、Goソースファイルに特定のコメント行を追加することで、そのファイルが特定の条件(オペレーティングシステム、アーキテクチャ、Goバージョンなど)が満たされた場合にのみコンパイルされるように制御するメカニズムです。 ビルドタグはファイルの先頭に// +build tagnameの形式で記述されます。複数のタグをスペースで区切って指定したり、カンマで区切ってOR条件を指定したり、!を付けてNOT条件を指定したりできます。

例:

  • // +build linux darwin:LinuxまたはmacOSでのみコンパイル
  • // +build !windows:Windows以外でコンパイル
  • // +build go1.18:Go 1.18以降でコンパイル

このコミットでは、// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windowsという行がenv_posix.cに追加されており、これはこのファイルが指定されたすべてのOSとnacl環境でコンパイルされるべきであることを意味します。

技術的詳細

このコミットは、GoランタイムがNative Client (NaCl) 環境でより堅牢に動作するための2つの主要な変更を含んでいます。

  1. mem_nacl.cへのSysFault関数の追加: mem_nacl.cは、Native Client環境におけるGoランタイムのメモリ管理に関連する低レベルの関数を実装しています。Goランタイムは、メモリの割り当て、解放、保護などの操作をOSに依存しない形で抽象化しています。しかし、実際のメモリ操作は各プラットフォームのシステムコールにマッピングされます。 SysFault関数は、特定のメモリ領域をアクセス不可に設定する役割を担います。これは、runtime·mmap関数をPROT_NONE(アクセス保護なし)フラグ付きで呼び出すことで実現されます。mmapはメモリをプロセスのアドレス空間にマッピングするためのシステムコールですが、PROT_NONEを指定することで、その領域への読み書き実行アクセスをすべて禁止します。これにより、Goランタイムが意図しないメモリアクセスを検出し、プログラムの安全性を高めることができます。NaCl環境では、通常のOSとは異なるメモリ保護の仕組みがあるため、NaCl固有のSysFaultの実装が必要とされました。

  2. env_posix.cのビルドタグへのnaclの追加: env_posix.cは、POSIX互換のオペレーティングシステム(Linux、macOS、FreeBSDなど)向けの環境変数やその他のシステム関連のランタイム関数を実装しています。Goのビルドシステムは、ソースファイルのビルドタグを読み取り、現在のターゲット環境に合致するファイルのみをコンパイルします。 この変更により、env_posix.cnacl環境向けにもコンパイルされるようになります。これは、Native ClientがPOSIXライクなインターフェースを提供するため、このファイルに含まれる汎用的なPOSIX環境関連のコードがNaCl環境でも利用できることを意味します。これにより、GoランタイムがNaCl環境で動作するために必要な環境設定やシステムコールラッパーが適切に提供されるようになります。

これらの変更は、GoランタイムがNaClのサンドボックス環境の制約と特性に適合し、メモリ保護のメカニズムを適切に利用し、必要な環境情報にアクセスできるようにするために不可欠です。

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

diff --git a/src/pkg/runtime/env_posix.c b/src/pkg/runtime/env_posix.c
index 746c7ee3fd..4c8288f6b4 100644
--- a/src/pkg/runtime/env_posix.c
+++ b/src/pkg/runtime/env_posix.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.\n
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
 
 #include "runtime.h"
 #include "arch_GOARCH.h"
diff --git a/src/pkg/runtime/mem_nacl.c b/src/pkg/runtime/mem_nacl.c
index 993d194dd5..b3cf91d7f0 100644
--- a/src/pkg/runtime/mem_nacl.c
+++ b/src/pkg/runtime/mem_nacl.c
@@ -53,6 +53,12 @@ runtime·SysFree(void *v, uintptr n, uint64 *stat)
 	runtime·munmap(v, n);
 }
 
+void
+runtime·SysFault(void *v, uintptr n)
+{
+	runtime·mmap(v, n, PROT_NONE, 0, -1, 0);
+}
+
 void*
 runtime·SysReserve(void *v, uintptr n)
 {

コアとなるコードの解説

src/pkg/runtime/env_posix.cの変更

--- a/src/pkg/runtime/env_posix.c
+++ b/src/pkg/runtime/env_posix.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.\n
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows

この変更は、env_posix.cファイルのビルドタグにnaclを追加しています。 元の行: // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows 変更後の行: // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows

これにより、Goのビルドツールは、ターゲット環境がnaclである場合にもこのenv_posix.cファイルをコンパイル対象に含めるようになります。env_posix.cは、POSIX互換システム向けの環境関連のランタイムコード(例えば、環境変数の取得など)を含んでいます。Native Client環境はPOSIXライクなインターフェースを提供するため、このファイルがNaClビルドに含まれることで、GoランタイムがNaCl環境で必要な環境情報を正しく取得できるようになります。

src/pkg/runtime/mem_nacl.cの変更

--- a/src/pkg/runtime/mem_nacl.c
+++ b/src/pkg/runtime/mem_nacl.c
@@ -53,6 +53,12 @@ runtime·SysFree(void *v, uintptr n, uint64 *stat)
 	runtime·munmap(v, n);
 }
 
+void
+runtime·SysFault(void *v, uintptr n)
+{
+	runtime·mmap(v, n, PROT_NONE, 0, -1, 0);
+}
+
 void*
 runtime·SysReserve(void *v, uintptr n)
 {

この変更は、mem_nacl.cファイルにruntime·SysFault関数を追加しています。 runtime·SysFault関数は、Goランタイムが特定のメモリ領域をアクセス不可に設定するために使用されます。 関数の実装は以下の通りです。

void
runtime·SysFault(void *v, uintptr n)
{
	runtime·mmap(v, n, PROT_NONE, 0, -1, 0);
}
  • void *v: 保護するメモリ領域の開始アドレス。
  • uintptr n: 保護するメモリ領域のサイズ(バイト単位)。
  • runtime·mmap(v, n, PROT_NONE, 0, -1, 0): これは、指定されたメモリ領域vからnバイトの範囲を、PROT_NONE(アクセス保護なし)フラグ付きで再マッピングするGoランタイムの内部関数呼び出しです。
    • PROT_NONE: このフラグは、指定されたメモリ領域への読み取り、書き込み、実行のすべてのアクセスを禁止します。これにより、この領域へのアクセスはセグメンテーションフォールトなどの例外を引き起こします。
    • 0, -1, 0: これらの引数は、mmapの他のパラメータ(フラグ、ファイルディスクリプタ、オフセット)に対応しますが、このコンテキストではメモリ保護の目的で匿名マッピング(ファイルに関連付けられていないメモリ)として使用されているため、通常は0や-1などの値が渡されます。

このSysFault関数の追加により、GoランタイムはNative Client環境において、メモリ保護違反をより効果的に検出し、処理できるようになります。これは、ガベージコレクタが解放したメモリ領域が誤って再利用されるのを防ぐなど、メモリ安全性を高める上で重要な役割を果たします。

関連リンク

参考にした情報源リンク