19.3. SELinux 関連の問題のトラブルシューティング
SELinux が無効になっていたシステムで SELinux を有効にする場合や、標準以外の設定でサービスを実行した場合は、SELinux がブロックできる状況のトラブルシューティングを行う必要がある可能性があります。ほとんどの場合、SELinux の拒否は、設定間違いによるものになります。
19.3.1. SELinux 拒否の特定
この手順で必要な手順のみを行います。ほとんどの場合は、ステップ 1 のみを実行する必要があります。
手順
SELinux がシナリオをブロックしたときに、最初に拒否に関する詳細情報を確認するのは
/var/log/audit/audit.log
ファイルとなります。Audit ログのクエリーには、ausearch
ツールを使用します。アクセスを許可する、または許可しないといった SELinux の決定はキャッシュされ、このキャッシュは AVC (アクセスベクターキャッシュ) として知られています。たとえば、メッセージタイプパラメーターにはAVC
およびUSER_AVC
の値を使用します。# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent
一致するものがない場合は、Audit デーモンが実行しているかどうかを確認します。実行していない場合は、
auditd
を起動して Audit ログを再確認してから、拒否されたシナリオを繰り返します。auditd
が実行中で、ausearch
の出力に一致がない場合は、systemd
ジャーナルが出力するメッセージを確認してください。# journalctl -t setroubleshoot
SELinux が有効で、Audit デーモンがシステムで実行していない場合は、
dmesg
コマンドの出力で特定の SELinux メッセージを検索します。# dmesg | grep -i -e type=1300 -e type=1400
以上の 3 つを確認しても、何も見つからない場合もあります。この場合、
dontaudit
ルールが原因で AVC 拒否を非表示にできます。一時的に
dontaudit
ルールを無効にし、すべての拒否をログに記録できるようにするには、以下のコマンドを実行します。# semodule -DB
以前の手順で、拒否されたシナリオを再実行し、拒否メッセージを取得したら、次のコマンドはポリシーで
dontaudit
ルールを再度有効にします。# semodule -B
これまでの 4 つのステップをすべて試し、それでも問題が解決しない場合は、SELinux がシナリオをブロックするかどうかを検討してください。
Permissive モードに切り替えます。
# setenforce 0 $ getenforce Permissive
- シナリオを繰り返します。
上記を試しても問題が発生する場合は、SELinux 以外に原因があります。
19.3.2. SELinux 拒否メッセージの分析
SELinux がシナリオをブロックしていることを 特定 したら、修正する前に原因分析が必要になる場合があります。
前提条件
-
policycoreutils-python-utils
パッケージおよびsetroubleshoot-server
パッケージがシステムにインストールされている。
手順
以下のように、
sealert
コマンドを実行して、ログに記録されている拒否の詳細をリスト表示します。$ sealert -l "*" SELinux is preventing /usr/bin/passwd from write access on the file /root/test. ***** Plugin leaks (86.2 confidence) suggests ***************************** If you want to ignore passwd trying to write access the test file, because you believe it should not need this access. Then you should report this as a bug. You can generate a local policy module to dontaudit this access. Do # ausearch -x /usr/bin/passwd --raw | audit2allow -D -M my-passwd # semodule -X 300 -i my-passwd.pp ***** Plugin catchall (14.7 confidence) suggests ************************** ... Raw Audit Messages type=AVC msg=audit(1553609555.619:127): avc: denied { write } for pid=4097 comm="passwd" path="/root/test" dev="dm-0" ino=17142697 scontext=unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0 ... Hash: passwd,passwd_t,admin_home_t,file,write
前の手順で取得した出力に明確な提案が含まれていない場合は、以下のコマンドを実行します。
完全パス監査を有効にして、アクセスしたオブジェクトの完全パスを表示し、追加の Linux Audit イベントフィールドが表示されるようにします。
# auditctl -w /etc/shadow -p w -k shadow-write
setroubleshoot
キャッシュを削除します。# rm -f /var/lib/setroubleshoot/setroubleshoot.xml
- 問題を再現します。
ステップ 1 を繰り返します。
プロセスが完了したら、完全パスの監査を無効にします。
# auditctl -W /etc/shadow -p w -k shadow-write
-
sealert
がcatchall
提案を返すか、audit2allow
ツールを使用して新しいルールを追加するように提案した場合は、Audit ログの SELinux 拒否 で説明されている例と問題を一致させます。
関連情報
-
システムの
sealert(8)
man ページ
19.3.3. 分析した SELinux 拒否の修正
ほとんどの場合、sealert
ツールが提供する提案により、SELinux ポリシーに関連する問題を修正するための適切なガイドが提供されます。SELinux 拒否のメッセージを解析 を参照してください。sealert
を使用して SELinux 拒否の解析方法を参照してください。
ツールが、audit2allow
ツールを使用して設定変更を提案している場合は注意が必要です。audit2allow
を使用して、SELinux 拒否を確認する際に、最初のオプションとしてローカルポリシーモジュールを生成することはできません。トラブルシューティングは、ラベル付けの問題があるかどうかを最初に確認します。2 番目に多いのが、SELinux が、プロセスの設定変更を認識していない場合です。
ラベル付けの問題
ラベル付けの問題の一般的な原因として、非標準ディレクトリーがサービスに使用される場合が挙げられます。たとえば、管理者が、Web サイト /var/www/html/
ではなく、/srv/myweb/
を使用したい場合があります。Red Hat Enterprise Linux では、/srv
ディレクトリーには var_t
タイプのラベルが付けられます。/srv
で作成されるファイルおよびディレクトリーは、このタイプを継承します。また、/myserver
などの最上位のディレクトリーに新規作成したオブジェクトには、default_t
タイプのラベルが付けられます。SELinux は、Apache HTTP Server (httpd
) がこの両方のタイプにアクセスできないようにします。アクセスを許可するには、SELinux では、/srv/myweb/
のファイルが httpd
からアクセス可能であることを認識する必要があります。
# semanage fcontext -a -t httpd_sys_content_t "/srv/myweb(/.*)?"
この semanage
コマンドは、/srv/myweb/
ディレクトリーおよびその下のすべてのファイルおよびディレクトリーのコンテキストを SELinux ファイルコンテキストの設定に追加します。semanage
ユーティリティーはコンテキストを変更しません。root で restorecon
ユーティリティーを使用して変更を適用します。
# restorecon -R -v /srv/myweb
コンテキストの誤り
matchpathcon
ユーティリティーは、ファイルパスのコンテキストを確認し、そのパスのデフォルトラベルと比較します。以下の例では、ラベルが間違っているファイルを含むディレクトリーにおける matchpathcon
の使用方法を説明します。
$ matchpathcon -V /var/www/html/*
/var/www/html/index.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
/var/www/html/page1.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
この例では、index.html
ファイルおよび page1.html
ファイルに、user_home_t
タイプのラベルが付けられています。このタイプは、ユーザーのホームディレクトリーのファイルに使用されます。mv
コマンドを使用してファイルをホームディレクトリーから移動すると、ファイルに user_home_t
タイプのラベルが付けられることがあります。このタイプは、ホームディレクトリーの外に存在してはなりません。このようなファイルを正しいタイプに復元するには、restorecon
ユーティリティーを使用します。
# restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:user_home_t:s0->system_u:object_r:httpd_sys_content_t:s0
ディレクトリー下の全ファイルのコンテキストを復元するには、-R
オプションを使用します。
# restorecon -R -v /var/www/html/
restorecon reset /var/www/html/page1.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0
標準以外の方法で設定された制限のあるアプリケーション
サービスはさまざまな方法で実行できます。この場合は、サービスの実行方法を指定する必要があります。これは、SELinux ポリシーの一部をランタイム時に変更できるようにする SELinux ブール値を使用して実行できます。これにより、SELinux ポリシーの再読み込みや再コンパイルを行わずに、サービスが NFS ボリュームにアクセスするのを許可するなどの変更が可能になります。また、デフォルト以外のポート番号でサービスを実行するには、semanage
コマンドを使用してポリシー設定を更新する必要があります。
たとえば、Apache HTTP Server が MariaDB と接続するのを許可する場合は、httpd_can_network_connect_db
のブール値を有効にします。
# setsebool -P httpd_can_network_connect_db on
-P
オプションを使用すると、システムの再起動後も設定が永続化されることに注意してください。
特定のサービスでアクセスが拒否される場合は、getsebool
ユーティリティーおよび grep
ユーティリティーを使用して、アクセスを許可するブール値が利用できるかどうかを確認します。たとえば、getsebool -a | grep ftp
コマンドを使用して FTP 関連のブール値を検索します。
$ getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_nfs --> off
ftpd_connect_db --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
ブール値のリストを取得し、ブール値が有効または無効かどうかを確認する場合は、getsebool -a
コマンドを使用します。ブール値のリストとその意味を取得し、有効かどうかを調べるには、selinux-policy-devel
パッケージをインストールして、root で semanage boolean -l
コマンドを実行します。
ポート番号
ポリシー設定によっては、サービスは特定のポート番号でのみ実行できます。ポリシーを変更せずにサービスが実行するポートを変更しようとすると、サービスが起動できなくなる可能性があります。たとえば、root で semanage port -l | grep http
コマンドを実行して、http
関連のポートを一覧表示します。
# semanage port -l | grep http
http_cache_port_t tcp 3128, 8080, 8118
http_cache_port_t udp 3130
http_port_t tcp 80, 443, 488, 8008, 8009, 8443
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989
http_port_t
ポートタイプは、Apache HTTP サーバーがリッスンできるポートを定義します。この場合は、TCP ポート 80、443、488、8008、8009、および 8443 です。httpd
がポート 9876 (Listen 9876
) でリッスンするように管理者が httpd.conf
を設定しても、これを反映するようにポリシーが更新されていない場合、以下のコマンドは失敗します。
# systemctl start httpd.service Job for httpd.service failed. See 'systemctl status httpd.service' and 'journalctl -xn' for details. # systemctl status httpd.service httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled) Active: failed (Result: exit-code) since Thu 2013-08-15 09:57:05 CEST; 59s ago Process: 16874 ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop (code=exited, status=0/SUCCESS) Process: 16870 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
以下のような SELinux 拒否メッセージのログは、/var/log/audit/audit.log
に記録されます。
type=AVC msg=audit(1225948455.061:294): avc: denied { name_bind } for pid=4997 comm="httpd" src=9876 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket
httpd
が http_port_t
ポートタイプに追加されていないポートをリッスンできるようにするには、semanage port
コマンドを使用して別のラベルをポートに割り当てます。
# semanage port -a -t http_port_t -p tcp 9876
-a
オプションは新規レコードを追加します。-t
オプションはタイプを定義し、-p
オプションはプロトコルを定義します。最後の引数は、追加するポート番号です。
進化または破損したアプリケーション、および侵害されたシステム (稀に発生する難しいケース)
アプリケーションにバグが含まれ、SELinux がアクセスを拒否する可能性があります。また、SELinux ルールは進化しています。アプリケーションが特定の方法で実行しているのを SELinux が認識しておらず、アプリケーションが期待どおりに動作していても、アクセスを拒否してしまうような場合もあります。たとえば、PostgreSQL の新規バージョンがリリースされると、現在のポリシーが考慮されないアクションが実行される可能性があり、アクセスが許可される場合でもアクセスが拒否されます。
このような状況では、アクセスが拒否された後に audit2allow
ユーティリティーを使用して、アクセスを許可するカスタムポリシーモジュールを作成します。SELinux ポリシーで足りないルールは Red Hat Bugzilla から報告できます。Red Hat Enterprise Linux 8 の場合は、製品で Red Hat Enterprise Linux 8
を選択し、selinux-policy
コンポーネントを選択してバグを作成します。このバグレポートに、audit2allow -w -a
コマンドおよび audit2allow -a
コマンドの出力を追加します。
アプリケーションが主要なセキュリティー特権を要求すると、そのアプリケーションが危険にさらされたことを示す警告が発生することがあります。侵入検出ツールを使用して、このような疑わしい動作を検証します。
また、Red Hat カスタマーポータル の Solution Engine では、同じ問題または非常に類似する問題に関する記事が提供されます。ここでは、問題の解決策と考えられる方法が示されています。関連する製品とバージョンを選択し、selinux、avc などの SELinux 関連のキーワードと、ブロックされたサービスまたはアプリケーションの名前 (selinux samba
など) を使用します。
19.3.4. Creating a local SELinux policy module
アクティブな SELinux ポリシーに特定の SELinux ポリシーモジュールを追加することで、SELinux ポリシーに関する特定の問題を修正できます。この手順を使用して、Red Hat リリースノート で説明されている特定の既知の問題を修正するか、特定の Red Hat ソリューション を実装できます。
Red Hat が提供するルールのみを使用します。Red Hat は、カスタムルールを使用した SELinux ポリシーモジュールの作成には対応していません。これは、製品サポートの対象範囲 外であるためです。専門家でない場合は、Red Hat の営業担当者に連絡し、コンサルティングサービスを依頼してください。
前提条件
-
検証用の
setools-console
パッケージおよびaudit
パッケージ。
手順
テキストエディターで新しい
.cil
を開きます。以下に例を示します。# vim <local_module>.cil
ローカルモジュールをより適切に整理するには、ローカル SELinux ポリシーモジュール名で接頭辞
local_
を使用します。既知の問題または Red Hat ソリューションからカスタムルールを挿入します。
重要独自のルールを作成しないでください。特定の既知の問題または Red Hat ソリューションで提供されているルールのみを使用します。
たとえば、SELinux denies cups-lpd read access to cups.sock in RHEL のソリューションを実装するには、以下の規則を挿入します。
(allow cupsd_lpd_t cupsd_var_run_t (sock_file (read)))
このサンプルソリューションは、RHBA-2021:4420 で RHEL 用に永続的に修正されました。したがって、このソリューションの特定の手順は更新済みの RHEL 8 システムおよび 9 システムに影響を与えず、構文のサンプルとしてのみ含まれています。
2 つの SELinux ルール構文 (Common Intermediate Language (CIL) と m4) のどちらかを使用できます。たとえば、CIL の
(allow cupsd_lpd_t cupsd_var_run_t (sock_file (read)))
は、m4 の以下と同じになります。module local_cupslpd-read-cupssock 1.0; require { type cupsd_var_run_t; type cupsd_lpd_t; class sock_file read; } #============= cupsd_lpd_t ============== allow cupsd_lpd_t cupsd_var_run_t:sock_file read;
- ファイルを保存してから閉じます。
ポリシーモジュールをインストールします。
# semodule -i <local_module>.cil
semodule -i
を使用して作成したローカルポリシーモジュールを削除する場合は、.cil
接尾辞のないモジュール名を参照してください。ローカルポリシーモジュールを削除するには、semodule -r <local_module>
を使用します。ルールに関連するサービスを再起動します。
# systemctl restart <service-name>
検証
SELinux ポリシーにインストールされているローカルモジュールをリスト表示します。
# semodule -lfull | grep "local_" 400 local_module cil
ローカルモジュールの優先順位は
400
であるため、semodule -lfull | grep -v ^100
コマンドを使用して、その値を使用してリストからそれらをフィルター処理することもできます。関連する許可ルールを SELinux ポリシーで検索します。
# sesearch -A --source=<SOURCENAME> --target=<TARGETNAME> --class=<CLASSNAME> --perm=<P1>,<P2>
<SOURCENAME>
はソースの SELinux の種類、<TARGETNAME>
はターゲットの SELinux の種類、<CLASSNAME>
はセキュリティークラスまたはオブジェクトクラスの名前、そして<P1>
と<P2>
はルール固有の権限です。たとえば、RHEL Red Hat Knowledgebase ソリューションで SELinux が cups.sock への cups-lpd の読み取りアクセスを拒否する ように実装するには、次の操作を実行します。
# sesearch -A --source=cupsd_lpd_t --target=cupsd_var_run_t --class=sock_file --perm=read allow cupsd_lpd_t cupsd_var_run_t:sock_file { append getattr open read write };
最後の行には、
read
操作が含まれているはずです。関連するサービスが SELinux に制限されて実行されていることを確認します。
関連するサービスに関連するプロセスを特定します。
$ systemctl status <service-name>
上記コマンドの出力でリスト表示されたプロセスの SELinux コンテキストを確認します。
$ ps -efZ | grep <process-name>
サービスが SELinux の拒否を引き起こさないことを確認します。
# ausearch -m AVC -i -ts recent <no matches>
-i
オプションは、数値を人間が判読できるテキストに解析します。
19.3.5. Audit ログの SELinux 拒否
Linux Audit システムは、デフォルトで /var/log/audit/audit.log
ファイルにログエントリーを保存します。
SELinux 関連の記録のみをリスト表示するには、メッセージタイプパラメーターの AVC
および AVC_USER
(並びに必要に応じたパラメーター) を付けて ausearch
コマンドを実行します。
# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR
Audit ログファイルの SELinux 拒否エントリーは次のようになります。
type=AVC msg=audit(1395177286.929:1638): avc: denied { read } for pid=6591 comm="httpd" name="webpages" dev="0:37" ino=2112 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:nfs_t:s0 tclass=dir
このエントリーで最も重要な部分は以下の通りです。
-
avc: denied
- SELinux によって実行され、アクセスベクターキャッシュ (AVC) で記録されるアクション -
{ read }
- 拒否の動作 -
pid=6591
- 拒否されたアクションの実行を試みたサブジェクトのプロセス ID -
comm="httpd"
- 分析しているプロセスを呼び出すのに使用されたコマンドの名前 -
httpd_t
- プロセスの SELinux タイプ -
nfs_t
- プロセスのアクションに影響するオブジェクトの SELinux タイプ -
tclass=dir
- ターゲットオブジェクトクラス
このログエントリーは、以下のように解釈できます。
SELinux が、nfs_t
タイプのディレクトリーから読み込む PID 6591 および httpd_t
タイプの httpd
プロセスを拒否します。
Apache HTTP Server が Samba スイートのタイプでラベル付けされたディレクトリーにアクセスしようとすると、以下の SELinux 拒否メッセージが発生します。
type=AVC msg=audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd" path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file
-
{ getattr }
-getattr
エントリーは、ターゲットファイルのステータス情報をソースプロセスが読み取ろうとしているのを示します。これは、ファイルを読み取る前に発生します。プロセスがファイルにアクセスし、適切なラベルがないため、SELinux はこのアクションを拒否します。一般的に表示されるパーミッションには、getattr
、read
、write
などが含まれます。 -
path="/var/www/html/file1"
- アクセスを試みたオブジェクト (ターゲット) へのパス。 -
scontext="unconfined_u:system_r:httpd_t:s0"
- 拒否されたアクションを試みたプロセス (ソース) の SELinux コンテキスト。この場合、Apache HTTP Server はhttpd_t
タイプで実行している SELinux コンテキストです。 -
tcontext="unconfined_u:object_r:samba_share_t:s0"
- プロセスがアクセスを試みたオブジェクト (ターゲット) の SELinux コンテキストです。この例では、これがfile1
の SELinux コンテキストです。
この SELinux 拒否は、以下のように解釈できます。
SELinux は、samba_share_t
タイプの /var/www/html/file1
ファイルにアクセスする PID 2465 の httpd
プロセスを拒否し、その他に許可するような設定がない場合は、httpd_t
ドメインで実行しているプロセスにアクセスできません。
関連情報
-
システムの
auditd(8)
およびausearch(8)
の man ページ
19.3.6. 関連情報
- CLI での基本的な SELinux トラブルシューティング (Red Hat ナレッジベース)
- Fedora People のプレゼンテーション - What is SELinux trying to tell me?SELinux エラーの 4 つの主な原因(フェドーラの人々)