めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

ファイル作成時に付与されるSELinuxのセキュリティコンテキスト

SELinuxの簡単な説明

SELinuxでは、事前に定義された「セキュリティポリシー」に従って、あるプロセスがアクセス可能なシステムリソース(ファイル、ネットワークポートなど)を制限することが可能です。RHEL6のデフォルトである「Targetedポリシー」では、RHEL6同梱のアプリケーションについて、事前にいくつかの制限がかけられています。

たとえば、RHEL6同梱のhttpdを導入した状態で、下記のように「/var/www/html/」以下にコンテンツファイルを作成します。

# mkdir /var/www/html/pub
# echo 'Hello World!' > /var/www/html/pub/index.html

できたディレクトリやファイルの「セキュリティコンテキスト」を表示すると、「httpd_sys_content_t」というキーワードが見えます。(lsに「-Z」オプションを付けるとディレクトリやファイルのセキュリティコンテキストが表示されます。)

# ls -lZd /var/www/html/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/
# ls -lZd /var/www/html/pub
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/pub
# ls -lZd /var/www/html/pub/index.html 
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/pub/index.html

Targetedポリシーの下では、httpdには、このセキュリティコンテキストを持つディレクトリ/ファイルを公開コンテンツとしてアクセスすることが許可されます。万一、httpdにセキュリティホールがあって、外部から動きを操作されたとしても、無関係なディレクトリへのアクセスはSELinuxによって阻止されるというわけです。

たとえば、rootのホームディレクトリにindex.htmlを作っても、下記のようにセキュリティコンテキストが異なるので、httpdからはアクセスできません。

# echo 'Hello World!' > /root/index.html
# ls -lZd /root/index.html 
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/index.html

新たに作成したファイルのセキュリティコンテキストは、親ディレクトリのセキュリティコンテキストに基づいて、セキュリティポリシーに従って決定されます。Targetedポリシーでは、規定のディレクトリ内に新規作成したファイルについては、適切なセキュリティコンテキストが自動設定されるようになっています。(逆に、規定外のディレクトリをアプリケーションから使用できるようにするには、いろいろ追加の作業が必要になります。)

セキュリティコンテキストが正しく付与されない場合

新規にファイルを作成するのではなく、既存のファイルをmvやcpで移動する場合は、セキュリティコンテキストが正しく付与されない場合があります。具体的には、次のようなパターンがあります。

1. 既存のファイルを同一ファイルシステム内でmvする、もしくは、「cp -a」などセキュリティコンテキストを保持するオプション付きでコピーする。
 ⇒ この場合、既存ファイルのセキュリティコンテキストがそのまま引き継がれます。

2. 既存のファイルに上書きコピーする。
 ⇒ この場合、コピー先の既存ファイルのセキュリティコンテキストがそのまま保持されます。

次の実行例をよく観察してみてください。

# mkdir /var/www/html/pub

# echo 'Hello World!' > /root/index.html
# cp /root/index.html /var/www/html/pub/index_cp.html # good
# cp -a /root/index.html /var/www/html/pub/index_cp-a.html # bad
# mv /root/index.html /var/www/html/pub/index_mv.html # bad

# echo 'Hello World!' > /var/www/html/pub/index_override.html
# echo 'Hello World!' > /root/index.html
# yes | cp /root/index.html /var/www/html/pub/index_override.html # good

# ls -lZ /var/www/html/pub/
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 index_cp-a.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_cp.html
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 index_mv.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_override.html

正しいセキュリティコンテキストが付与されなかったファイルは、restoreconコマンドで正しいセキュリティコンテキストを付与することができます。次のように「-R」オプションを使うと、指定のディレクトリ以下のファイルすべてを再帰的に処理します。

# restorecon -R /var/www/html/pub
# ls -lZ /var/www/html/pub/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_cp-a.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_cp.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_mv.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index_override.html

この他には、新しく用意したファイルシステムを「/var/www/html」ディレクトリとしてマウントした場合は、マウントしたディレクトリにセキュリティコンテキストの設定も必要です。

# restorecon -R /var/www/html

「SELinuxが原因かな?」と思った際は

まずは、「/var/log/messages」もしくは「/var/log/audit/audit.log」に、下記のような「avc: denied」というメッセージが記録されていないか確認します。

Nov 12 13:35:08 kakinoha kernel: type=1400 audit(1352694908.612:495153): avc:  denied  { getattr } for  pid=1341 comm="httpd" path="/var/www/html/pub/index_mv.html" dev=sda2 ino=262537 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file

この例では、「httpd」が「/var/www/html/pub/index_mv.html」にアクセスしようとして拒絶されていることがすぐに分かります。

テスト環境であれば、setenforceコマンドで、SELinuxを一時的に「Permissive」モードに変更して、切り分けを行うのもよいでしょう。Permissiveモードでは、ポリシー違反は、ログに記録するだけで、実際にはアクセスは拒絶されません。

# setenforce 0
# getenforce 
Permissive

再度、「Enforcing」モードに戻すには、次のコマンドを実行します。

# setenforce 1
# getenforce 
Enforcing