これまで使ってたCGIを移設したら動かなくなって、その理由がselinuxのポリシーだった。 ポリシーの作り方と書き換え方をメモ。

環境はCentOS6.6で、kernel 2.6.32、apache2.2.15 この上でブラウザからjavaを実行しようとしたら

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007fcf589ac000, 2555904, 1) failed; error='Permission denied' (errno=13)
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 2555904 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /tmp/jvm-21000/hs_error.log



とりあえずPermission deniedなことはわかったけど、なんのパーミッションがないのか分からず、検索したところ

In case anyone else is looking for a way to resolve this without explicitly disabling SELinux, the wiki page at helped me understand what was going on.
By default, the security context that Java is running in when called from Apache does not allow things like reading a file, allocating memory, accessing the network etc. The easiest way to resolve these errors is by using the semodule and audit2allow applications. Essentially, check the SELinux audit log (could be /var/logs/audit/audit.log, but I used /var/log/messages and extracted the avc errors). In the log you should see things like
linux - Run java in php apache2 - Super User

ということでどうやらselinuxだからメモリアロケーションの権限が無いらしい。ここに書いてあるwiki HowTos/SELinux - CentOS Wiki に解決法があった。

audit.logというログファイルをもとに追加するポリシーを作成するらしい。 まず作成・登録するためのツール群が入ってなかったのでインストール

$ sudo yum install policycoreutils-python

あとはcentos wikiと同じだけど、javaなので

$ sudo grep java_t /var/log/audit/audit.log | audit2allow -m javalocal > javalocal.te


module javalocal 1.0;

require {
        type httpd_sys_script_t;
        class process execmem;

#============= httpd_sys_script_t ==============

#!!!! This avc is allowed in the current policy
allow httpd_sys_script_t self:process execmem;


上のようにcentos wikiに書いてあるとおりやったけど、下のように後から全部を読み込ませても同じ結果になることを確認した。audit2allowが良きに計らってくれるらしい。

$ sudo cat /var/log/audit/audit.log | audit2allow -m javalocal > javalocal.te


$ sudo grep java_t /var/log/audit/audit.log | audit2allow -M javalocal


$ sudo semodule -i javalocal.pp