パーミッションを正しく設定しても CGI の実行に失敗する場合 (CentOS 5.4)


パーミッションを設定しても 500 エラーが発生する

CentOS 5.4 上で稼働している Apache 2.2.3 で CGI を動作させてみたところ、パーミッションやスクリプトエンジンへのパスが正しく設定されているにも関わらず、"500 Internal Server Error" となり、正しく動作しませんでした。

Apache のエラーログを確認すると、次のようなエラーが検出されています。

(13)Permission denied: exec of '/home/html/test.cgi' failed, referer: http://localhost/test/

いろいろ調べてみたところ、どうやらこれは SELinux というセキュリティーポリシーによってアクセス制御がされているために発生するもののようでした。

特に CGI の実行の場合、今のところ分かっている限りでは、ファイルに対して execute ioctl execute_no_trans の許可が必要になってくる様子です。

 

SELinux を設定するためには、"setenforce 0" を実行して SELinux を Permissive モードで起動した上で、httpd を起動させます。

すると、SELinux の影響で起動できなくなっている場合には正しく動作するようになるので、まずは次のようにして httpd がどの SELinux ドメインで実行されているかを確認します。

ps -eZ | grep httpd

これで、出力結果の ":" で区切られた 3 番目の内容から、Apache (httpd) が "httpd_t" ドメイン内で動作していることが分かります。

後はこのドメインに対して適切な許可を追加することになります。

 

試してみた感じでは、以下の許可設定を追加すれば大丈夫なようでした。

もしかすると、新しいパスにログファイルが作成されていないために、それを新規作成しようとして発生したエラーなのかもしれません。

module httpd 1.0;

require {
type transproxy_port_t;
type cert_t;
type httpd_config_t;
type file_t;
type httpd_t;
require {
type transproxy_port_t;
type cert_t;
type httpd_config_t;
type file_t;
type httpd_t;
type user_home_t;
type reserved_port_t;
type port_t;
type var_lib_t;
type amanda_port_t;
type tmp_t;
type soundd_port_t;
type mysqld_port_t;
class sock_file write;
class tcp_socket name_bind;
class tcp_socket name_connect;
class dir { write search getattr add_name read };
class file { ioctl getattr read create execute append execute_no_trans };
}

#============= httpd_t ==============
allow httpd_t amanda_port_t:tcp_socket name_bind;
allow httpd_t cert_t:file execute;
allow httpd_t file_t:dir { write search getattr add_name };
allow httpd_t file_t:file { create ioctl append getattr };
allow httpd_t httpd_config_t:file execute;
allow httpd_t port_t:tcp_socket name_bind;
allow httpd_t reserved_port_t:tcp_socket name_bind;
allow httpd_t soundd_port_t:tcp_socket name_bind;
allow httpd_t tmp_t:sock_file write;
allow httpd_t transproxy_port_t:tcp_socket name_bind;
allow httpd_t user_home_t:dir { getattr search read };
allow httpd_t user_home_t:file { read getattr execute ioctl execute_no_trans };
allow httpd_t var_lib_t:sock_file write;
allow httpd_t mysqld_port_t:tcp_socket name_connect;

ただ、それぞれのパスの中での関係ファイルの取り扱いについて、SELinux の許可設定を行う必要があるようですので、設定ファイル内のパスに応じても上記内容は変わってくるかもしれません。

なお、SELinux の設定方法については Linux のセキュリティ設定 (SELinux) の方に記してありますので、そちらを参考にしてください。