SELinuxのポリシー・モジュールを自作する
audit2allowコマンドを使えば自動生成されるけど、いくつかの問題があるときに何度も実行してマージするのが面倒臭くて、audit.logを見ながらポリシー・モジュールを手書きしてたら、きもいって言われたけど、きもくないのを主張するために書きます。
環境は次の通り。
muninの mysql_ はinnodbの状態とかを収集してくれるプラグインで、実態は mysqladmin extended-status で取得できる情報を収集するものです。これをSELinuxを有効にしてると、次のようなエラーメッセージがログ ( /var/log/munin-node/munin-node.log ) に表示されます(一部のみ)。
2013/05/01-23:40:11 [60227] Error output from mysql_qcache_mem:
2013/05/01-23:40:11 [60227] Couldn't instantiate IPC::ShareLite: Permission denied at /usr/share/perl5/Cache/SharedMemoryBackend.pm line 85.
2013/05/01-23:40:11 [60227] Service 'mysql_qcache_mem' exited with status 13/0.
これはSELinuxがアクセスを不許可にしてるようで、 /var/log/audit/audit.log ファイルにdeniedで出力されています(一部のみ)。
type=AVC msg=audit(1367418934.828:49833): avc: denied { unix_read unix_write } for pid=59897 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm setroubleshoot-serverパッケージがインストールされていれば、/var/log/messages ファイルに ..... run sealert -l xxxxxx みたいなメッセージが出力されてて、sealertコマンドを実行すると、
grep xxxx /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp
を実行してねってメッセージが表示されるので、実行すると、ポリシー・ソースファイルのmypol.teファイルとコンパイルされたmypol.ppファイルが作成されて、semodule -i mypol.pp を実行するとSELinuxに新しいポリシーが登録されます。
けれど、上記に貼りつけたログのように、たくさんあるときは一つづつ確認するのが面倒だし、場合によっては、このポリシーをクリアした後、別のポリシーを要求されることもあります。なので、最初からポリシー・ファイルを作成したほうが楽な場合があるのです。
以下、muninのmysql_プラグインが動くためのポリシーを作成します。
ポリシー名はmypolで作成します。
touch mypol.te
ファイルにポリシー名とバージョンを記述します。
module mypol 1.0;
今回はドメインで設定するので、audit.logに書かれたscontextとtcontextの転んで区切った三番目のもの (ドメイン属性) を記述します。上記のログだと munin_services_plugin_tだけなので、これを記述します。
require {
type munin_services_plugin_t;
}
さらにこのrequireのブロック内に、audit.logに書かれたtclassと、denied { xxxx } の括弧内の内容を次の書式で記述します。
class shm { unix_read unix_write };
その後、scontext, tcontextの先ほどの三番目のものとtclassとdenied { xxxx } の括弧内のものを次のように記述します。
allow munin_services_plugin_t munin_services_plugin_t:shm { unix_read unix_write };
今回はscontextとtcontextのものが同じなので、selfで置き換えられます。
allow munin_services_plugin_t self:shm { unix_read unix_write };
結果的に、こうなります。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write };
これは、audit.ogが、アクセス・ドメインが munin_services_plugin_t (scontextに書かれたもの) のプロセスmysql_innodb_bpなど (commに書かれたもの) が munin_services_plugin_t (tcontextに書かれたもの)に対して shmクラス (tclassに書かれたもの) でunix_read, unix_write (deniedの後の括弧に書かれたもの) を実行しようとしたが許可されていない、と言っているのに対する設定です。requireで必要なリソースを列挙し、allowでscontextがtcontextに{xxxx}を実行することを許可する、と定義します。
ポリシー・ファイルを作成したので、これをコンパイルします。
make -f /usr/share/selinux/devel/Makefile
実行すると、mypol.fc, mypol.if, mypol.ppを作成しますが、fc, ifファイルは今のところ不要です。ppファイルがコンパイルされたポリシー・モジュールです。これをSELinuxに適用します。
semodule -i mypol.pp
ここで、私の環境では期待通りに別のSELinuxに却下されたメッセージが出力されました。/var/log/audit/audit.log に次のようなメッセージが出力されてます (全部同じなので、1つだけ)。
type=AVC msg=audit(1367422400.503:58827): avc: denied { associate } for pid=65203 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
これを見る限り、scontextがtcontextにshmでassociateを実行する許可が必要なようです。そこで、require内のshmにassociateを追加して、allowにassociateを追加します。すなわち、こうなります。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write associate };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate };
これをコンパイルして、SELinuxに適用します。同じ名前のものを最適用するときは、
semodule -r mypol
semodule -i mypol.pp
で削除・登録をするか、
semodule -i mypol.pp
semodule -R
で再登録して、リロードします。すると、また別のメッセージが出力されます。
type=AVC msg=audit(1367423040.036:60463): avc: denied { read write } for pid=1188 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
今度は read, write が許可されていないと言っているので、先ほどと同じように、requireのclassとallowに追加します。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write associate read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write };
これをコンパイルして再登録すると、更に別のメッセージが出力されました。
type=AVC msg=audit(1367423459.872:62107): avc: denied { read write } for pid=2367 comm="mysql_innodb_io" path=2F535953563633363337303639202864656C6574656429 dev=tmpfs ino=229383 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:object_r:tmpfs_t:s0 tclass=file
今度は今までと違うものがtcontextとtclassに出力されました。tmpfs_t が登場したので、require内にtypeを追加します。また、fileのread, writeが却下されてるので、classを追加します。
type tmpfs_t;
class file { read write };
そして、munin_services_plugin_tからこれらに対するアクセスを許可します。
allow munin_services_plugin_t tmpfs_t:file { read write };
結果として、次のようになります。
module mypol 1.0;
require {
type munin_services_plugin_t;
type tmpfs_t;
class shm { unix_read unix_write associate read write };
class file { read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write };
allow munin_services_plugin_t tmpfs_t:file { read write };
これをコンパイルして再登録すると、また別のメッセージが出力されました。
type=AVC msg=audit(1367424118.516:63758): avc: denied { getattr } for pid=3842 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
今回は munin_services_plugin_t 自身に getattr するのを許可するだけなので、class shm とallow ... self:shm にgetattr を追加するだけです。
module mypol 1.0;
require {
type munin_services_plugin_t;
type tmpfs_t;
class shm { unix_read unix_write associate read write getattr };
class file { read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write getattr };
allow munin_services_plugin_t tmpfs_t:file { read write };
これをコンパイルして再登録した所、ようやくメッセージがでなくなり、muninがmysql_ プラグインから値を収集できるようになりました。
このあと、それぞれのファイルのラベル付が正しいかとかをチェックして、不要な設定を極力なくしていく作業がありますが、それは私のSELinux力がもう少し付いてから。
ちなみに、これをするまでに学ばせてもらったのは、こちらの資料です。
http://www.slideshare.net/ishikawa84g/hbstudy-28-selinuxhandson
60-61ページ:/var/log/messages の見方
83-85, 96ページ:/var/log/audit/audit.log の見方
106-110ページ:ポリシーの作成方法
追記
munin_ のラベルを munin_services_plugin_t って書いたけど、最初からそうだったのか、自分でchconしたのか覚えてません。。。