[インデックス 10350] ファイルの概要
このコミットは、Go言語のビルドシステムにおけるSELinux (Security-Enhanced Linux) の検出ロジックを修正するものです。具体的には、Fedora 16でSELinuxのファイルシステムが従来の/selinux
ではなく/sys/fs/selinux
にマウントされるようになった変更に対応し、make.bash
スクリプトが両方のパスを適切にチェックするように改善されています。これにより、Fedora 16環境下でGoのビルドがSELinuxのallow_execstack
設定によって中断される問題を解決します。
コミット
- コミットハッシュ:
90c5070000d1db22409dd5b97b3a3bb777021b03
- 作者: Bobby Powers bobbypowers@gmail.com
- コミット日時: 2011年11月11日 16:41:37 -0500
- 変更ファイル:
src/make.bash
(1ファイル) - 変更行数: 18行追加, 13行削除
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/90c5070000d1db22409dd5b97b3a3bb777021b03
元コミット内容
build: fix check for selinux's allow_execstack on Fedora 16
Fedora 16 mounts selinux at /sys/fs/selinux, instead of the
traditional /selinux. Check both locations for the selinux
filesystem in make.bash
Fixes #2448.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5373077
変更の背景
この変更は、Go言語のビルドプロセスがSELinuxが有効なシステム、特にFedora 16で問題なく動作するようにするために行われました。
Go言語のコンパイラやランタイムは、実行時にスタックの実行を許可する(execstack
)必要があります。これは、Goのコンパイラが生成するコードが、一部の最適化やランタイムの動作のために、実行可能なスタック領域を必要とするためです。SELinuxは、セキュリティを強化するために、デフォルトでスタックの実行を制限するポリシーを持つことがあります。
Goのビルドスクリプトであるmake.bash
は、SELinuxが有効なシステムでallow_execstack
が有効になっているかどうかをチェックし、もし無効であれば警告を表示するロジックを含んでいました。しかし、Fedora 16ではSELinuxのファイルシステムのマウントポイントが従来の/selinux
から/sys/fs/selinux
に変更されました。この変更により、make.bash
スクリプトがSELinuxのステータスを正しく検出できなくなり、結果としてGoのビルドが不必要に警告を発したり、場合によっては失敗したりする可能性がありました。
この問題は、GoのIssueトラッカーでIssue #2448として報告されており、このコミットはその問題を解決するために作成されました。
前提知識の解説
SELinux (Security-Enhanced Linux)
SELinuxは、Linuxカーネルに組み込まれた強制アクセス制御 (MAC: Mandatory Access Control) セキュリティメカニズムです。従来の任意アクセス制御 (DAC: Discretionary Access Control) とは異なり、システム管理者が定義したセキュリティポリシーに基づいて、プロセスやユーザーがファイル、デバイス、その他のリソースにアクセスする方法を厳密に制限します。これにより、たとえroot権限を持つプロセスが侵害されたとしても、その被害を最小限に抑えることができます。
SELinuxは、ファイルやプロセスに「コンテキスト」と呼ばれるセキュリティラベルを付与し、ポリシーに基づいてこれらのコンテキスト間の相互作用を制御します。
allow_execstack
allow_execstack
は、SELinuxのブーリアン(真偽値)設定の一つです。このブーリアンがon
(有効)に設定されている場合、プログラムがスタック領域を実行可能にすることを許可します。多くの現代的なシステムでは、セキュリティ上の理由から、スタック領域は実行不可(NXビット、DEPなど)に設定されています。これは、バッファオーバーフロー攻撃などによって悪意のあるコードがスタックに注入され、実行されるのを防ぐためです。
しかし、一部のアプリケーションやコンパイラ(Go言語を含む)は、動的に生成されたコードや特定の最適化のために、実行可能なスタックを必要とすることがあります。allow_execstack
がoff
の場合、そのようなプログラムは正しく動作しないか、起動すらできない可能性があります。
setsebool
コマンド
setsebool
コマンドは、SELinuxのブーリアン設定を変更するために使用されます。例えば、setsebool -P allow_execstack 1
というコマンドは、allow_execstack
ブーリアンを永続的にon
(1)に設定します。-P
オプションは、変更を永続化し、システム再起動後も設定が保持されるようにします。
Go言語のビルドプロセスと make.bash
Go言語のソースコードからコンパイラや標準ライブラリをビルドする際には、通常、src/make.bash
(Unix系システムの場合)またはsrc/make.bat
(Windowsの場合)スクリプトが使用されます。これらのスクリプトは、Goのツールチェインをブートストラップし、必要なバイナリをコンパイルし、テストを実行する役割を担っています。
make.bash
スクリプトは、ビルド環境の様々な側面をチェックし、潜在的な問題をユーザーに警告するロジックを含んでいます。SELinuxのallow_execstack
のチェックもその一部です。
SELinuxのマウントポイントの変更 (/selinux
から /sys/fs/selinux
)
Linuxシステムでは、SELinuxのステータスや設定を管理するためのファイルシステムが特定のパスにマウントされます。伝統的に、これは/selinux
にマウントされていました。しかし、Linuxカーネルの進化とファイルシステム階層標準 (FHS: Filesystem Hierarchy Standard) の改善に伴い、一部のディストリビューション(Fedora 16など)では、SELinuxのファイルシステムが/sys/fs/selinux
にマウントされるようになりました。これは、/sys
がカーネルやデバイスに関する情報を提供する仮想ファイルシステムのマウントポイントとしてより適切であるという考えに基づいています。
この変更は、SELinuxのステータスやブーリアン設定をプログラム的にチェックするスクリプトに影響を与えます。スクリプトが古いパスのみをチェックしている場合、新しいマウントポイントではSELinuxが有効であっても検出できなくなります。
技術的詳細
このコミットの技術的な核心は、make.bash
スクリプトがSELinuxのファイルシステムを検出するロジックを強化した点にあります。
変更前は、スクリプトはSELinuxの存在を/selinux
ディレクトリの有無によってのみ判断していました。
if [ -d /selinux -a -f /selinux/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
# ... 既存のチェックロジック ...
fi
このロジックは、Fedora 16のようにSELinuxが/sys/fs/selinux
にマウントされているシステムでは機能しませんでした。
コミット後の変更では、SELinuxのファイルシステムがマウントされている可能性のある複数のパス(/selinux
と/sys/fs/selinux
)をループで順にチェックするように改善されました。
for se_mount in /selinux /sys/fs/selinux
do
if [ -d $se_mount -a -f $se_mount/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
# ... 既存のチェックロジック ...
fi
done
この変更により、スクリプトはまず/selinux
をチェックし、もしSELinuxがそこにマウントされていなければ、次に/sys/fs/selinux
をチェックします。これにより、異なるLinuxディストリビューションやバージョンにおけるSELinuxのマウントポイントの差異を吸収し、より堅牢な検出メカニズムを提供します。
ループ内で、以下の条件が満たされる場合にのみ、allow_execstack
のチェックと警告メッセージの表示が行われます。
$se_mount
で指定されたディレクトリが存在する (-d $se_mount
)。$se_mount/booleans/allow_execstack
ファイルが存在する (-f $se_mount/booleans/allow_execstack
)。/usr/sbin/selinuxenabled
実行ファイルが存在し、かつ実行可能である (-x /usr/sbin/selinuxenabled
)。/usr/sbin/selinuxenabled
コマンドが成功する(SELinuxが有効であることを示す)。
これらの条件がすべて満たされた上で、allow_execstack
ブーリアンの値が1 1
(有効)でない場合に、Goのビルドに必要な設定が不足している旨の警告が表示されます。
コアとなるコードの変更箇所
--- a/src/make.bash
+++ b/src/make.bash
@@ -50,21 +50,26 @@ chmod +x "$GOBIN"/gomake
# TODO(brainman): delete this after 01/01/2012.
rm -f "$GOBIN"/gotest # remove old bash version of gotest on Windows
-if [ -d /selinux -a -f /selinux/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
-\tif ! cat /selinux/booleans/allow_execstack | grep -c '^1 1$' >> /dev/null ; then
-\t\techo "WARNING: the default SELinux policy on, at least, Fedora 12 breaks "
-\t\techo "Go. You can enable the features that Go needs via the following "
-\t\techo "command (as root):"\n-\t\techo " # setsebool -P allow_execstack 1"
-\t\techo
-\t\techo "Note that this affects your system globally! "
-\t\techo
-\t\techo "The build will continue in five seconds in case we "
-\t\techo "misdiagnosed the issue..."
+# on Fedora 16 the selinux filesystem is mounted at /sys/fs/selinux,
+# so loop through the possible selinux mount points
+for se_mount in /selinux /sys/fs/selinux
+do
+\tif [ -d $se_mount -a -f $se_mount/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
+\t\tif ! cat $se_mount/booleans/allow_execstack | grep -c '^1 1$' >> /dev/null ; then
+\t\t\techo "WARNING: the default SELinux policy on, at least, Fedora 12 breaks "
+\t\t\techo "Go. You can enable the features that Go needs via the following "
+\t\t\techo "command (as root):"\n+\t\t\techo " # setsebool -P allow_execstack 1"
+\t\t\techo
+\t\t\techo "Note that this affects your system globally! "
+\t\t\techo
+\t\t\techo "The build will continue in five seconds in case we "
+\t\t\techo "misdiagnosed the issue..."
\n-\t\tsleep 5
+\t\t\tsleep 5
+\t\tfi
\tfi
-fi
+done
\n
(\n \tcd "$GOROOT"/src/pkg;
コアとなるコードの解説
変更の中心は、SELinuxのチェックを行うif
文がfor
ループで囲まれた点です。
-
for se_mount in /selinux /sys/fs/selinux
:- この行は、
se_mount
という変数に、SELinuxのファイルシステムがマウントされている可能性のある2つのパス(/selinux
と/sys/fs/selinux
)を順に代入しながらループを実行することを意味します。 - これにより、スクリプトはまず従来のパスを試し、次にFedora 16などで採用されている新しいパスを試すことができます。
- この行は、
-
if [ -d $se_mount -a -f $se_mount/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
:- この
if
文は、ループの各イテレーションで、現在の$se_mount
パスが有効なSELinuxマウントポイントであるかどうかをチェックします。 -d $se_mount
:$se_mount
がディレクトリとして存在するかどうかをチェックします。-a -f $se_mount/booleans/allow_execstack
:$se_mount/booleans/allow_execstack
ファイルが存在するかどうかをチェックします。このファイルはallow_execstack
ブーリアンの現在の状態を格納しています。-a -x /usr/sbin/selinuxenabled
:/usr/sbin/selinuxenabled
コマンドが存在し、実行可能であるかをチェックします。このコマンドはSELinuxが有効かどうかを判断するために使用されます。&& /usr/sbin/selinuxenabled
: 上記のファイルシステムチェックが成功した場合に、実際にselinuxenabled
コマンドを実行し、その終了ステータスが成功(SELinuxが有効)であるかをチェックします。- これらの条件がすべて真である場合、内側の
if
ブロックが実行されます。
- この
-
内側の
if
ブロックのインデントとsleep
の修正:- ループの導入に伴い、既存の警告ロジック全体が
for
ループと内側のif
文のスコープ内に適切にインデントされました。 sleep 5
の行も、内側のif
文のスコープ内に適切に移動し、インデントが修正されています。
- ループの導入に伴い、既存の警告ロジック全体が
この変更により、make.bash
はSELinuxのマウントポイントの差異を透過的に処理できるようになり、Goのビルドプロセスがより多くのLinux環境で安定して動作するようになりました。
関連リンク
- Go Change-Id (Gerrit): https://golang.org/cl/5373077
- Go Issue #2448: https://github.com/golang/go/issues/2448
参考にした情報源リンク
- SELinux Project: https://selinuxproject.org/page/Main_Page (一般的なSELinux情報)
- Fedora Project Documentation (Fedora 16リリースノートなど): https://fedoraproject.org/wiki/Documentation (Fedora 16におけるSELinuxパス変更の確認)
setsebool
man page: (Linuxシステム上でman setsebool
で参照可能)make.bash
の役割に関するGoのドキュメント: (Goの公式ドキュメントやソースコード内のコメント)
(注:上記「参考にした情報源リンク」は、実際のWeb検索で得られる可能性のある情報源の例です。この解説の生成においては、提供されたコミット情報と一般的な知識に基づいて記述されています。)