1. SELinuxの設定

1.1. SELinux 設定ファイル

OSは起動時に"/etc/selinux/config"というファイルを読み込み、SELinuxのstate, typeを決定します。 初期設定は以下の通りです。

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 

SELINUXはSELinux stateを決定するパラメータで、SELINUXTYPEはSELinux typeを決定するパラメータです。 各パラメータに設定できる値は以下の通りです。

パラメータ意味
SELINUXenforcingSELinuxのポリシーに反する動作を全て拒否します
SELINUXpermissiveSELinuxのポリシーに反する動作に対し警告のログを出力します
SELINUXdisabledSELinuxを無効化します
SELINUXTYPEtargeteddhcpd, httpdなどの代表的なデーモンのみが制御対象となります
SELINUXTYPEstrict全てのデーモンが制御対象となります
SELINUXTYPEMLS上記にRBAC(ロールベースアクセス制御)を追加し、strictよりも厳格な動作をします

1.2. SELinux 設定変更および設定確認

"/etc/selinux/config"を書き換える事でSELinux stateを変更できますが、 setenforceコマンドを使用する事でも、OS再起動なしにSELinux stateを変更できます。 引数にpermissive (または0), enforce (または1)を与える事でstateを指定する事ができます。 (但し、setenforceコマンドでSELinux stateをdisableにする事はできません。 disableに変更するためには"/etc/selinux/config"を書き換え、OS再起動が必要になります。) 実行例は以下の通りです。

[root@fedora16 ~]# setenforce 1

SELinuxの設定確認を行うにはgetenforce, sestatusなどのコマンドを使用します。

[root@fedora16 ~]# getenforce
Enforcing
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 26
Policy from config file:        targeted
[root@fedora16 ~]#

1.3. SELinuxの無効化

そもそも、SELinuxは政府機関や金融機関からの厳格なセキュリティ要求を満たすために開発された機能です。 政府機関や金融機関からのよっぽどの強い要望がない限りはSELinuxを無効にする事をお勧めします (殆どの場合は、守るべき情報資産の価値よりもSELinuxのメンテナンスコストの方が大きくなってしまいます)。

SELinuxを無効にするためには、"/etc/selinux/config"のSELINUXパラメータを disableに変更する事で対応できます。

[root@fedora16 ~]# vi /etc/selinux/config 

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 

1.4. SELinuxの有効化

SELinuxを無効の状態から有効の状態に変更するには、注意が必要です。 必ずpermissive modeにしてからOSを一度再起動する事をお勧めします。 OS起動に必要な権限が与えられておらず、OS起動ができなくなってしまう恐れがあるからです。

permissive modeでOS再起動を行ったら、SELinuxのポリシー違反がない事を確認してから enforce modeに変更します。SELinuxのポリシー違反は"/var/log/audit/audit.log"にdeniedと記載されます。 確認例は以下の通りです。

[root@fedora16 tmp]# grep denied /var/log/audit/audit.log 
[root@fedora16 tmp]#

万が一、SELinuxによってOSが起動できなくなった場合は、 以下のようにGRUBの画面で起動パラメータに"selinux=0"を与える事で、 SELinuxが無効の状態で起動させる事ができます。

なお、以前、私は誤って"SELINUXTYPE=disabled"と入力したところ、 OSすら起動できない状態になってしまいました。

2. SELinux 動作概要

2.1. セキュリティポリシー

SELinuxはセキュリティポリシーで定義された動作のみを許可します。 明示的に許可されていない動作は全て禁止されます(いわゆる、"ホワイトリスト", "暗黙のdeny all"です)。

セキュリティポリシーは、"誰が(Subject)" "何に(Object)" "何をできるか(Action)"の集合です。 例えば、以下は"Webサーバが、HTML文書を、読み込める"というポリシーになります。

allow httpd_t http_sys_content_t : file { read } ;

実際のセキュリティーポリシーは、sesearchというコマンドで調べる事ができます。 seseachはsetools-consoleというパッケージ内に含まれていますでの、yumなどでインストールして下さい。

yum -y install setools-console

seseachの使用例は以下の通りです。 なお、大かっこ ( "[", "]" )で囲まれた部分はBooleanと呼ばれる値で、 この値が真か偽かによってアクセス権を制御する変数です。

[root@fedora16 ~]# sesearch -A -C -s httpd_t -t httpd_sys_content_t -c file
Found 3 semantic av rules:
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
DT allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename execute open } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]
ET allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ; [ httpd_builtin_scripting ]

[root@fedora16 ~]#

2.2. セキュリティコンテキスト

SELinuxでは、ファイル・プロセス・ソケットなどあらゆるリソースに対して セキュリティコンテキストと呼ばれるアクセス可否を判断する属性が付与されています。 このセキュリティコンテキストを確認するためには、 ls, ps, idなどの一般的なコマンドに-Zオプションを付ける事で確認できます。

[root@fedora16 ~]# ps -Z
LABEL                             PID TTY          TIME CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 931 pts/0 00:00:00 bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10637 pts/0 00:00:00 ps
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# ls -Z
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 install.log
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 install.log.syslog
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@fedora16 ~]#

セキュリティコンテキストはセミコロン区切りで4つのフィールドに分かれます。 各フィールドの意味は、右から順に以下の通りです。 なお、この中で最もトラブル対応で役立つのは、"タイプ属性"です。 初学者は、最低限"タイプ属性"だけは覚えておくようにすると良いと思います。

属性意味
ユーザ属性system_uサブジェクトやオブジェクトに割り当てるSELinuxのユーザID
ロール属性object_rユーザに割り当てる権限の範囲を定義したもの。ロールが不要なオブジェクトにはダミーロール(object_r)が付与されます。
ユーザ属性admin_home_tSELinuxがアクセス可否を判定する時に使用するセキュリティ属性
機密ラベルs0組織・役職などで分ける識別子

3. trouble shoot セキュリティコンテキストの再割当

3.1. トラブル概要

以下、apacheがインストールされている前提で話を進めます。 apache, iptablesなどSELinux以外の設定については、説明を省略します。

以下の手順でindex1.htmlとindex2.htmlを公開します。

[root@fedora16 ~]# echo 'It Works!' > /var/www/html/index1.html
[root@fedora16 ~]# echo 'It Works!' > ~/index2.html
[root@fedora16 ~]# mv ~/index2.html /var/www/html/index2.html

wgetなどで動作確認を行うとindex1.htmlは正常に応答しますが、index2.htmlは403エラーを返します。 この403エラーの原因についてトラブルシュートを行います。

[root@fedora16 ~]# wget -O - http://localhost/index1.html
--2011-12-25 11:23:52--  http://localhost/index1.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It Works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 11:23:52 (1.19 MB/s) - `-' へ保存完了 [10/10]

[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/index2.html
--2011-12-25 11:23:55--  http://localhost/index2.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
2011-12-25 11:23:55 エラー 403: Forbidden。

[root@fedora16 ~]#

3.2. 切り分け

一番最初にやるべき切り分けは、SELinuxによる権限不足なのか、それ以外の問題なのかの切り分けです。 SELinuxをpermissive modeにして想定通りの動作をするか否かで、SELinuxなのかそれ以外なのかを判別できます。

[root@fedora16 ~]# setenforce permissive
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Permissive
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/index2.html
--2011-12-25 11:27:21--  http://localhost/index2.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It Works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 11:27:21 (1.22 MB/s) - `-' へ保存完了 [10/10]

[root@fedora16 ~]#

permissive modeにすると正常応答するので、SELinuxによってアクセスが拒否されている事が推測できます。

3.3. セキュリティコンテキスト 再割当

SELinuxのログを確認します。 /var/www/html/index2.htmlに対して、getattr, readなどのシステムコールが許可されていない事が読み取れます。

さらに詳しくログを読み解きます。 scontext・tcontextは、それぞれソース・ターゲットのセキュリティコンテキストを表します。 つまり、"root:system_r:httpd_t:s0"が"root:object_r:user_home_t:s0"に対して getattr, readできない旨を以下ログが表しています。

[root@fedora16 ~]# grep denied /var/log/audit/audit.log
type=AVC msg=audit(1324866235.726:38757): avc:  denied  { getattr } for  pid=19324 comm="httpd" path="/var/www/html/index2.html" dev=sda5 ino=2336513 scontext=root:system_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1324866235.727:38758): avc:  denied  { getattr } for  pid=19324 comm="httpd" path="/var/www/html/index2.html" dev=sda5 ino=2336513 scontext=root:system_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1324866441.083:38761): avc:  denied  { getattr } for  pid=19325 comm="httpd" path="/var/www/html/index2.html" dev=sda5 ino=2336513 scontext=root:system_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1324866441.083:38762): avc:  denied  { read } for  pid=19325 comm="httpd" name="index2.html" dev=sda5 ino=2336513 scontext=root:system_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
[root@fedora16 ~]#

/var/www/html配下のファイルのセキュリティコンテキストを確認します。 index1.htmlのユーザ属性はhttpd_sys_content_tなのでhttpdから読取可能ですが、 index2.htmlのユーザ属性はuser_home_tなのでhttpdから読取不可である事が分かりました。

[root@fedora16 ~]# ll -Z /var/www/html/
-rw-r--r--  root root root:object_r:httpd_sys_content_t index1.html
-rw-r--r--  root root root:object_r:user_home_t        index2.html
[root@fedora16 ~]#

セキュリティコンテキストは、 どのディレクトリにファイルが作成されたかによって自動的に作成されます。 ファイルを移動した場合は、セキュリティコンテキストの再割当をする事によって対応が可能です。 restorecon コマンドを使用する事でセキュリティコンテキストの再割当ができます。

[root@fedora16 ~]# restorecon -RF /var/www/html
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# ll -Z /var/www/html/
-rw-r--r--  root root system_u:object_r:httpd_sys_content_t index1.html
-rw-r--r--  root root system_u:object_r:httpd_sys_content_t index2.html
[root@fedora16 ~]#
[root@fedora16 ~]# setenforce enforcing
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Enforcing
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/index2.html
--2011-12-25 12:04:36--  http://localhost/index2.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It Works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 12:04:36 (1.21 MB/s) - `-' へ保存完了 [10/10]

[root@fedora16 ~]#

4. trouble shoot booleanの編集

4.1. トラブル概要

ユーザディレクトリの公開を許可します。 11行目, 18行目を以下のように編集し、httpdを再起動します。

[root@fedora16 ~]# vi /etc/httpd/conf/httpd.conf

 omitted


    #
    # UserDir is disabled by default since it can confirm the presence
    # of a username on the system (depending on home directory
    # permissions).
    #
    #UserDir disable

    #
    # To enable requests to /~user/ to serve the user's public_html
    # directory, remove the "UserDir disable" line above, and uncomment
    # the following line instead:
    #
    UserDir public_html



[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# /etc/init.d/httpd restart
httpd を停止中:                                            [  OK  ]
httpd を起動中:                                            [  OK  ]
[root@fedora16 ~]#

sampleユーザを作成し、公開ディレクトリにindex.htmlを配布します。 しかし、index.htmlの取得を試みると、403エラーを返されます。このエラーの原因について考察します。

[root@fedora16 ~]# useradd sample
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# su - sample
[sample@fedora16 ~]$ mkdir ~/public_html
[sample@fedora16 ~]$ echo 'It works!' > ~/public_html/index.html
[sample@fedora16 ~]$ chmod -R a+x /home/sample
[sample@fedora16 ~]$
[sample@fedora16 ~]$
[sample@fedora16 ~]$ wget http://localhost/~sample/index.html
--2011-12-25 12:22:16--  http://localhost/~sample/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
--2011-12-25 12:22:16 エラー 403: Forbidden。

[sample@fedora16 ~]$

4.2. 切り分け

切り分けを行うために、一時的にpermissive modeに変更します。 permissive modeでは正常応答を返す事から、SELinuxによってアクセスが拒否されている事が推測できます。

[root@fedora16 ~]# setenforce 0
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Permissive
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/~sample/index.html
--2011-12-25 12:30:06--  http://localhost/~sample/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 12:30:06 (1.23 MB/s) - `-' へ保存完了 [10/10]

[root@fedora16 ~]#

4.3. エラー原因の確認

エラーの原因を確認するためenforcing modeに戻します。 余計なログを排除するために一度"/var/log/audit/audit.log"を消します。 その後、wgetコマンドを実行し、エラーログを出力させます。

[root@fedora16 ~]# setenforce 1
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Enforcing
[root@fedora16 ~]#
[root@fedora16 ~]# echo "" > /var/log/audit/audit.log
[root@fedora16 ~]# wget -O - http://localhost/~sample/index.html
--2011-12-25 12:30:42--  http://localhost/~sample/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
2011-12-25 12:30:42 エラー 403: Forbidden。

[root@fedora16 ~]#

ログを確認します。"system_r:httpd_t"が"user_home_dir_t"に対して、 seach, getattrする権利がない事が分かりました。

[root@fedora16 ~]# grep denied /var/log/audit/audit.log
type=AVC msg=audit(1325006754.076:50): avc:  denied  { search } for  pid=1177 comm="httpd" name="sample" dev=dm-1 ino=786943 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
type=AVC msg=audit(1325006768.147:52): avc:  denied  { search } for  pid=1179 comm="httpd" name="sample" dev=dm-1 ino=786943 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
type=AVC msg=audit(1325006768.147:53): avc:  denied  { getattr } for  pid=1179 comm="httpd" path="/home/sample" dev=dm-1 ino=786943 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
[root@fedora16 ~]#

"system_r:httpd_t"が"user_home_dir_t"に対して"何ができるか"を確認します。 ポリシーを表示されるには、以下のようにsesearchコマンドを実行して下さい。 実行結果から、search, getattrが認められるかどうかは、 "httpd_enable_homedirs", "httpd_read_user_content"のboolean次第である事が分かります。

[root@fedora16 ~]# sesearch -A -C -s httpd_t -t user_home_dir_t -c dir
Found 2 semantic av rules:
DT allow httpd_t user_home_dir_t : dir { getattr search open } ; [ httpd_enable_homedirs ]
DT allow httpd_t user_home_dir_t : dir { ioctl read getattr lock search open } ; [ httpd_read_user_content ]

[root@fedora16 ~]#

4.4. boolean の変更

booleanの値を書きかえるには、setseboolというコマンドを使用します。 boolean書き換え後、wgetが成功する事を確認して下さい。 なお、以下の設定はOS再起動時に消えてしまいます。 OS再起動後も設定を反映させたい場合は、setseboolオプションに-Pオプションを付けて下さい。

[root@fedora16 ~]# setsebool httpd_enable_homedirs 1
[root@fedora16 ~]# setsebool httpd_read_user_content 1
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/~sample/index.html
--2011-12-25 18:30:49--  http://localhost/~sample/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 18:30:49 (588 KB/s) - stdout へ出力完了 [10/10]

[root@fedora16 ~]#

5. trouble shoot セキュリティポリシーの作成

5.1. トラブル概要

/wwwをDocumentRootとして公開し、index.htmlを作成します。

[root@fedora16 ~]# mkdir /www
[root@fedora16 ~]# echo 'It works!' > /www/index.html
[root@fedora16 ~]# chmod -R 777 /www
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# vi /etc/httpd/conf/httpd.conf

  omitted

#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
#DocumentRoot "/var/www/html"
DocumentRoot "/www"
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# /etc/init.d/httpd restart
Restarting httpd (via systemctl):                          [  OK  ]
[root@fedora16 ~]#
[root@fedora16 ~]#

index.htmlの取得を試みると403エラーが返されます。 この原因について考察します。

[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-25 19:07:10--  http://localhost/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
2011-12-25 19:07:10 エラー 403: Forbidden。

[root@fedora16 ~]#

5.2. 切り分け

切り分けを行うために、一時的にpermissive modeに変更します。 permissive modeでは正常応答を返す事から、SELinuxによってアクセスが拒否されている事が推測できます。

[root@fedora16 ~]# setenforce 0
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Permissive
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-25 19:12:45--  http://localhost/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 19:12:45 (540 KB/s) - stdout へ出力完了 [10/10]

[root@fedora16 ~]#

5.3. エラー原因の確認

エラーの原因を確認するためenforcing modeに戻します。 その後、wgetコマンドを実行し、エラーログを出力させます。

[root@fedora16 ~]# setenforce 1
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# getenforce
Enforcing
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# echo "" > /var/log/audit/audit.log
[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-25 19:23:11--  http://localhost/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
2011-12-25 19:23:11 エラー 403: Forbidden。

[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# grep denied /var/log/audit/audit.log
type=AVC msg=audit(1325010191.936:73): avc:  denied  { getattr } for  pid=1312 comm="httpd" path="/www/index.html" dev=dm-1 ino=522242 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
type=AVC msg=audit(1325010191.936:74): avc:  denied  { getattr } for  pid=1312 comm="httpd" path="/www/index.html" dev=dm-1 ino=522242 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
[root@fedora16 ~]#

セキュリティポリシーを確認すると、このエラーに該当するポリシーは存在しない事が分かります。 従って、wgetを許可するためにはセキュリティポリシーを作成する必要があります。

[root@fedora16 ~]# sesearch -A -C -s httpd_t -t default_t -c file

[root@fedora16 ~]#

5.4. セキュリティポリシーの作成

"http_d"は"httpd_sys_content_t"に対して、read, getattrする事ができます。 従って、/www配下に作成されたファイルに対してユーザ属性"httpd_sys_content_t"を付与するよう セキュリティポリシーを編集します。

セキュリティポリシーはsemanageコマンドを使用して編集します。 semanageはpolicycoreutils-pythonパッケージに含まれていますので、 以下容量でpolicycoreutils-pythonをインストールして下さい。

[root@fedora16 ~]# yum -y install policycoreutils-python

以下のようにセキュリティポリシーを作成します。 その後、セキュリティコンテキストを再割当するためにrestoreconコマンドを実行します。 wgetで正常応答が返ってくる事を確認して下さい。

[root@fedora16 ~]# semanage fcontext -a -t httpd_sys_content_t "/www/.*"
[root@fedora16 ~]# restorecon -RF v /www
[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-25 19:51:51--  http://localhost/index.html
localhost をDNSに問いあわせています... 127.0.0.1
localhost|127.0.0.1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 10 [text/html]
`STDOUT' に保存中

 0% [                                       ] 0           --.-K/s              It works!
100%[======================================>] 10          --.-K/s 時間 0s

2011-12-25 19:51:51 (615 KB/s) - stdout へ出力完了 [10/10]

[root@fedora16 ~]#
[root@fedora16 ~]#

6. セキュリティポリシーの自動生成

6.1. 設定削除

/var/log/audit/audit.logからセキュリティポリシーを作成するのが、非常に困難な場合もあります。 そのような場合、最終手段として、audit.logからセキュリティポリシーを自動生成する手法もあります。 (但し、許可してはいけないポリシーを許可してしまうリスクは非常に高いです。)

以前の手順で作成したセキュリティポリシーを自動生成する手法を紹介します。 まず、以前の手順で投入したセキュリティポリシーを削除します。

[root@fedora16 ~]# semanage fcontext -d -t httpd_sys_content_t "/www/.*"
[root@fedora16 ~]# restorecon -RF v /www

6.2. ログの生成

不要なログを削除した後に、audit.logにエラーログを記録させます。

[root@fedora16 ~]# echo -n "" > /var/log/audit/audit.log
[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-24 03:41:37--  http://localhost/index.html
localhost をDNSに問いあわせています... ::1
localhost|::1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden
2011-12-24 03:41:37 エラー 403: Forbidden。

[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# cat /var/log/audit/audit.log
type=AVC msg=audit(1324665697.577:246): avc:  denied  { getattr } for  pid=21744 comm="httpd" path="/www/index.html" dev=dm-1 ino=522242 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file
type=SYSCALL msg=audit(1324665697.577:246): arch=40000003 syscall=195 success=no exit=-13 a0=20e80340 a1=bfb9fbb0 a2=cf5ff4 a3=8170 items=0 ppid=21741 pid=21744 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1324665697.577:247): avc:  denied  { getattr } for  pid=21744 comm="httpd" path="/www/index.html" dev=dm-1 ino=522242 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file
type=SYSCALL msg=audit(1324665697.577:247): arch=40000003 syscall=196 success=no exit=-13 a0=20e803c8 a1=bfb9fbb0 a2=cf5ff4 a3=2008171 items=0 ppid=21741 pid=21744 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
[root@fedora16 ~]#

6.3. セキュリティポリシーの生成

audit.logからセキュリティポリシーを生成するには、audit2allowコマンドを使用します。 -mでポリシー名を指定しますが、ポリシー名は重複しない名前ならば特に指定はありません。

生成されたポリシーは語尾が.teで終わるファイルに出力して下さい。 その後、以下の要領でコンパイルし、local.ppというファイルが作成された事を確認します。

[root@fedora16 ~]# audit2allow -R -i /var/log/audit/audit.log -m local > local.te
[root@fedora16 ~]# make -f /usr/share/selinux/devel/Makefile
Compiling targeted local module
/usr/bin/checkmodule:  loading policy configuration from tmp/local.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 14) to tmp/local.mod
Creating targeted local.pp policy package
rm tmp/local.mod.fc tmp/local.mod
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# ll
合計 1296
-rw-------. 1 root root    1096 12月 21 20:43 anaconda-ks.cfg
-rw-r--r--. 1 root root   12783 12月 21 20:43 install.log
-rw-r--r--. 1 root root    4995 12月 21 20:42 install.log.syslog
-rw-r--r--. 1 root root       0 12月 24 03:49 local.fc
-rw-r--r--. 1 root root      23 12月 24 03:49 local.if
-rw-r--r--. 1 root root   61354 12月 24 03:49 local.pp
-rw-r--r--. 1 root root     128 12月 24 03:46 local.te
[root@fedora16 ~]#

6.4. セキュリティポリシーの読込

セキュリティポリシーを読み込むにはsemduleコマンドを用います。 -iオプションでインストールし、-Rオプションでリストアします。

[root@fedora16 ~]# semodule -i local.pp
[root@fedora16 ~]# semodule -l | grep local
local   1.0
locallogin      1.10.2
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# semodule -R
[root@fedora16 ~]#
[root@fedora16 ~]#
[root@fedora16 ~]# wget -O - http://localhost/index.html
--2011-12-24 03:54:33--  http://localhost/index.html
localhost をDNSに問いあわせています... ::1
localhost|::1|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 11 [text/html]
`STDOUT' に保存中

 0% [                                                                                                                 ] 0           --.-K/s              It works!

100%[================================================================================================================>] 11          --.-K/s 時間 0s

2011-12-24 03:54:33 (627 KB/s) - stdout へ出力完了 [11/11]

[root@fedora16 ~]#