SELinuxってたまに聞くけど中身は全然知らなかったのですが、今回Fedora 17のChromeでNativeClientが動かなかったので設定することにしました。
■ SELinuxって何じゃらホイ
SELinuxって名前は聞いたことあって、セキュリティ系の機能らしいというのは知っているのですが、それ以上のことはよく知りませんでした…。
というわけで、調べてみました。第1回 セキュアOS機能「SELinux」の基本的な仕組み。ちょっと古い記事ですが、まあ問題ないでしょう。
私の理解したところによると。
今までの普通のLinuxには、chmodで設定するような、ユーザーやグループを用いたアクセス制御がありますが、この場合は万が一root権限で動くプロセスを奪取されるとすべてにアクセスし放題になってしまってよろしくありません。というわけで、SELinuxではそれとは別にプログラム単位で色々な制限を、ファイルへのアクセス制限だけでなく、もっと色々な行動への制限が掛けられるようになっている…ということみたいです。
…間違ってたらゴメンネ。例えばhttpdにはネットワーク接続の権限が必要だけど、passwdへのアクセスは要らないから、これを制限しよう、という発想だと理解しました。これをTE(Type-Enforcement)と言うそうです。
RABCっていう別の仕組みもあるそうですが、今回引っかかったのはTEなのでこちらに話を絞ります
■Fedora 17でGoogle ChromeのNative Clientが動かない
さて。今回引っかかったのはGoogle ChromeのNative Clientです。SDKに入っているexampleを試しに動かしてみましたが…こんな感じで動いてくれません。
うまく行くとこうなるはずなんですけどー!
で、まずはGoogleで検索してみたのですが、どうやら今回のSELinuxが問題で動かないようになっているようだ、という事が分かりました。
■まずは全体を無効にしてみる
まずは、SELinux全体を無効にしてみました。
% sudo setenforce Permissive
こうすると全体のSELinuxが無効になります。で、この状態でさっきのExampleが綺麗に表示されたので、SELinuxが問題だと分かります。
あとで有効に戻すには次のコマンドを使って下さい。無効にしたままは流石にどうかと思うので…
% sudo setenforce Enforcing
■さらに細かい粒度で有効か無効かを調べる
とりあえずSELinuxの問題であることがわかったので、Chromeのどういうモジュールなのかなあというのを調べるために、プロセスのドメインごとに有効無効を切り替えられるツールを使います
% sudo yum install policycoreutils-gui
どうやらChromeにはsandboxとsandbox_naclという2つのドメインが割り当てられているようです(この割り当て自体はFedoraの中の人がやってるようです)。どう考えても後者が怪しいので、Permissiveボタンを押してnaclの方をPermissiveモード(SELinux無効)にしてみると…やっぱり動作しました。これが問題みたいです。
■AuditのログからSELinux用のモジュールを作る
SELinuxを一時的に解除して動くようにしましたが、SELinuxはアクセス制御は行なっていませんが、ログを、Auditdというデーモンのログに記録しています。Fedoraの場合は/var/log/audit/audit.logに入っております。
このAuditというデーモン、syslogdみたいな感じらしいです。でもSyslogdよりリッチなシステムらしいです。詳しくはLinux Audit 〜OSレベルの監査ログ徹底活用〜が参考になります。
このログの中で、chrome nacl…といったキーワードを調べていくと、chrome_sandbox_nacl_tというのがnacl関連だと思われるので、それでgrepします。
%sudo grep ":chrome_sandbox_nacl_t:" /var/log/audit/audit.log
さらにこれでログを抽出した上で、audit2allowというプログラムを用いて、SELinuxでの設定ファイル、モジュールを作る事ができます。
%sudo grep ":chrome_sandbox_nacl_t:" /var/log/audit/audit.log | audit2allow -a -l r require { type chrome_sandbox_nacl_t; type chrome_sandbox_t; class unix_dgram_socket { read write }; } #============= chrome_sandbox_nacl_t ============== allow chrome_sandbox_nacl_t chrome_sandbox_t:unix_dgram_socket { read write };
さらに、-M module名とすると、モジュールのコンパイルもしてくれます。
% sudo grep ":chrome_sandbox_nacl_t:" /var/log/audit/audit.log | audit2allow -a -l -r -M chrome_sandbox_nacl
で、最後にsemodule -iを使ってインストールします。
% sudo module -i chrome_sandbox_nacl.pp
以上です。さっきのGUIでnaclだけPermissiveにしていたのを元に戻してEnforcingにしても、ちゃんとnaclが動作するようになるはずです!
■モジュールを作らなくても大丈夫な場合もある
今回はモジュールを作りましたが、正直言って結構大工事でしたね。それ以外にも、getsebool/setseboolで設定できるフラグや、ファイルのタイプを変更する方法でもSELinuxの制限を何とか出来たりもするようです。が、今回は駄目でした。
■SELinuxは分かりづらい。
SELinuxは他のLinuxのデーモンなどと違い、設定ファイルがバイナリにコンパイルされた状態で保存されています。(/etc/selinuc/targetd/以下)。速度が重要な所ですから、多分そのためだとは思うのですが、いまいち分かりづらいです。
上記で使ったaudit2allowの代わりに、audit2whyというのを使うと制限された理由を教えてくれたりもするようです。
type=AVC msg=audit(1345883976.560:36379): avc: denied { read write } for pid=15643 comm="nacl_helper_boo" path="socket:[667837]" dev="sockfs" ino=667837 scontext=unconfined_u:unconfined_r:chrome_sandbox_nacl_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:chrome_sandbox_t:s0-s0:c0.c1023 tclass=unix_dgram_socket Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access.
Missingって…。Fedoraの中の人のミスじゃないかなあ、これ…。