SELinuxでApacheからのファイルへのアクセスを許可する
SELinuxが有効になっていると、ファイルシステム上のパーミッションは問題ないはずなのにApacheや同プロセス内で動くPHPからファイルにアクセスできないことがある。
ログファイルの場所を標準とは異なる場所に指定すると、ログの記録に失敗することもある。
ディストリビューションの標準構成ではあらかじめ/var/www/にhttpd_sys_content_tがついているのでApacheがそのコンテンツをサービスできる。
Apacheから読み出しが必要なファイルやディレクトリにはSELinuxのタイプhttpd_sys_content_tを付与する。
Apacheから書き込みが必要なファイルやディレクトリにはSELinuxのタイプhttpd_sys_rw_content_tを付与する。
エラーのログ
/var/log/messages
ログファイルが吐き出せないというエラーはApacheプロセスから/var/log/messagesに吐き出されていた。
code:grep "home/www" messages*
messages-20201220:Dec 18 15:16:39 www httpd209843: (13)Permission denied: AH00091: httpd: could not open error log file /home/www/logs/error_log.
messages-20201220:Dec 18 15:16:57 www httpd209855: (13)Permission denied: AH00091: httpd: could not open error log file /home/www/logs/error_log.
/var/log/audit/audit.log
ApacheのロードしたPHPモジュールが外部のサイトにTCPで接続しようとして拒否された様子が吐き出されていた。AVCはアクセスベクタ制御のことである。
code:ausearch -i -l -m avc -if /var/log/audit/audit.log | grep http
type=AVC msg=audit(12/15/20 07:34:03.127:21246) : avc: denied { name_connect } for pid=103987 comm=php-fpm dest=80 scontext=system_u:system_r:httpd_t:s0 tcontext=
system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0
type=AVC msg=audit(12/15/20 07:49:19.857:21280) : avc: denied { name_connect } for pid=103982 comm=php-fpm dest=80 scontext=system_u:system_r:httpd_t:s0 tcontext=
system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0
デフォルトではSELinuxのログはauditd経由で/var/log/audit/audit.logに吐き出される。
auditdが動いていなければ/var/log/messagesに吐き出される。
たいていのSELinuxに関するメッセージはAVCというキーワードで区別される。
dmesg
ポリシーをロードしましたとかそういうのが出てるっぽい。
code:dmesg | grep SELinux
0.001891 SELinux: Initializing.
2.778990 SELinux: policy capability network_peer_controls=1
2.778991 SELinux: policy capability open_perms=1
2.778991 SELinux: policy capability extended_socket_class=1
2.778991 SELinux: policy capability always_check_network=0
2.778992 SELinux: policy capability cgroup_seclabel=1
2.778992 SELinux: policy capability nnp_nosuid_transition=1
2.799719 systemd1: Successfully loaded SELinux policy in 405.062ms.
3625367.221768 SELinux: Converting 2428 SID table entries...
3625367.352693 SELinux: Context system_u:system_r:ejabberd_t:s0-s0:c0.c1023 became invalid (unmapped).
3625368.028315 SELinux: Context unconfined_u:system_r:ejabberd_t:s0-s0:c0.c1023 became invalid (unmapped).
3625368.583951 SELinux: policy capability network_peer_controls=1
3625368.583952 SELinux: policy capability open_perms=1
3625368.583952 SELinux: policy capability extended_socket_class=1
3625368.583953 SELinux: policy capability always_check_network=0
3625368.583953 SELinux: policy capability cgroup_seclabel=1
3625368.583954 SELinux: policy capability nnp_nosuid_transition=1
6013385.630342 SELinux: Converting 2442 SID table entries...
6013386.992331 SELinux: policy capability network_peer_controls=1
6013386.992332 SELinux: policy capability open_perms=1
6013386.992332 SELinux: policy capability extended_socket_class=1
6013386.992333 SELinux: policy capability always_check_network=0
6013386.992333 SELinux: policy capability cgroup_seclabel=1
6013386.992334 SELinux: policy capability nnp_nosuid_transition=1
6298897.115703 SELinux: Converting 2453 SID table entries...
6298898.478471 SELinux: policy capability network_peer_controls=1
6298898.478472 SELinux: policy capability open_perms=1
6298898.478473 SELinux: policy capability extended_socket_class=1
6298898.478473 SELinux: policy capability always_check_network=0
6298898.478473 SELinux: policy capability cgroup_seclabel=1
6298898.478474 SELinux: policy capability nnp_nosuid_transition=1
セキュリティコンテキストの確認
lsコマンドに-Zオプションをつけるとセキュリティコンテキストも表示できる。
code:ls -alFZ /var/www
drwxr-xr-x. 5 root root system_u:object_r:httpd_sys_content_t:s0 43 Oct 7 15:23 ./
drwxr-xr-x. 21 root root system_u:object_r:var_t:s0 4096 Oct 6 07:59 ../
drwxr-xr-x. 2 root root system_u:object_r:httpd_sys_script_exec_t:s0 6 Sep 16 00:46 cgi-bin/
drwxr-xr-x. 2 root root system_u:object_r:httpd_sys_content_t:s0 42 Oct 6 17:22 html/
drwxrwxr-x. 2 hoge hoge unconfined_u:object_r:httpd_sys_content_t:s0 23 Dec 16 12:34 wp/
chconによるタイプの付与
Apacheプロセスに対して読み出しを許可したいならhttpd_sys_content_tを付与する。
Apacheプロセスに対して書き込みも許可したいならhttpd_sys_rw_content_tを付与する。
親ディレクトリ(この場合は/home/wwwにまで付与する必要はないらしい。
タイプは一つだけ付けられる
httpd_sys_content_tのついているファイルやディレクトリにhttpd_sys_rw_content_tを付与するとタイプは上書きされる。
タイプは子に伝播しない
-Rオプションで再帰的にタイプを適用する
$ chcon -R -h -t httpd_sys_content_t /home/www/wp
table:各ディレクトリのコンテキスト
/var/www system_u object_r httpd_sys_content_t s0
/var/www/wp unconfined_u object_r httpd_sys_content_t s0
/home/www unconfined_u object_r user_home_dir_t s0
/home/www/wp unconfined_u object_r user_home_dir_t s0 chconによる変更の前
/home/www/wp unconfined_u object_r httpd_sys_content_t s0 chconによる変更の後
セキュリティコンテキストの復元
chconによるセキュリティコンテキストの変更は一時的なので、restoreconなどにより戻されてしまう。
restorecon -R -v /home/www/wpとすれば元に戻ってしまうはず。-nオプションでdry runできる。
code:restorecon -n -R -v /home/www | head
Would relabel /home/www/wp from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:user_home_t:s0
以下略
参考
Apache設定 ファイル権限問題がないのに 403 Permission denied file permissions deny server access の対策
SELinux コンテキスト - ファイルのラベルづけ
永続的な変更: semanage fcontext
CentOS HowTos SELinux