- 技術 💻
SELinuxでPermission deniedになる原因|確かめ方と直し方
パーミッション(chmod・chown)が正しいのに Permission denied になるときは、SELinux が止めていることがあります。 SELinux が止めると、監査ログ(/var/log/audit/audit.log)に avc: denied の行が残るので、まずそれを探します。
getenforce # Enforcing なら SELinux が止めている可能性がある
sudo ausearch -m AVC,USER_AVC -ts recent -i # 直近の拒否ログ(-i で読みやすく)
sudo sealert -l "*" # 原因と直し方の候補(setroubleshoot-server が要る)
直し方は、たいてい次の3つのどれかです。 setenforce 0 や audit2allow は最初に使うものではありません。
| 原因 | よくある例 | 直し方 |
|---|---|---|
| ファイルのラベルが違う | /home で作って /var/www/html へ mv した、/srv/web に置いた |
semanage fcontext -a → restorecon -Rv |
| boolean(スイッチ)が off | Web アプリから DB や外部 API につながらない、NFS 上のファイルを読む | setsebool -P httpd_can_network_connect_db on など |
| ポートのラベルが無い | Apache・nginx・sshd を標準でないポートで起動したい | semanage port -a -t http_port_t -p tcp 8081 |
確認環境:SELinux の仕様と AVC ログの例は、Red Hat Enterprise Linux 9 の公式ドキュメント「Using SELinux」の原文で確かめました。boolean の説明と既定値・ポートの割り当ては、Fedora・RHEL が使うポリシーのソース(fedora-selinux/selinux-policy、2026年10月7日のコミット)で確かめています。audit2allow・ausearch・semanage・matchpathcon・sesearch は Ubuntu 24.04 の SELinux のツール(policycoreutils 3.5・setools 4.4.4・audit 3.1.2)と、Ubuntu のポリシー(Reference Policy 2.20240202)で動かしました。このマシンのカーネルでは SELinux が無効のため、ファイルへのラベル付け(restorecon・chcon)とポリシーの読み込みは、ドキュメントと man ページで確かめています(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「SELinuxでPermission deniedになる原因|確かめ方と直し方」
SELinux が原因かを切り分ける
flowchart TD
A["Permission denied"] --> B{"getenforce"}
B -- "Disabled / Permissive" --> X["SELinux は止めていない<br/>(Permissive はログだけ残す)"]
B -- "Enforcing" --> C{"ausearch -m AVC で<br/>denied の行があるか"}
C -- "ある" --> D["tcontext の type を見る<br/>sealert で候補を見る"]
C -- "ない" --> E{"semodule -DB で<br/>dontaudit を外して再現"}
E -- "出た" --> D
E -- "出ない" --> F["chmod・chown・ACL・<br/>マウントオプションを疑う"]
D --> G["ラベル → boolean → ポート<br/>の順に直す"]
1. SELinux が動いているか
getenforce # Enforcing / Permissive / Disabled
sestatus # モード・ポリシー名(targeted など)をまとめて表示
| モード | 動き |
|---|---|
| Enforcing | ポリシーにない操作を止めて、ログに残す |
| Permissive | 止めずに、ログだけ残す(permissive=1) |
| Disabled | 何もしない。ログも残らない |
2. 拒否ログ(AVC)を探す
Red Hat のドキュメントでは、次の順で探す手順になっています。
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent # 直近10分
sudo ausearch -m AVC -ts today -i # 今日の分を読みやすく
sudo journalctl -t setroubleshoot # setroubleshoot の要約
sudo dmesg | grep -i -e type=1300 -e type=1400 # auditd が止まっているとき
| オプション | 意味 |
|---|---|
-m AVC |
メッセージの種類で絞る。AVC が SELinux の拒否 |
-ts recent |
直近10分。today・yesterday・this-week、-ts 10:00 のような時刻も書ける |
-i |
数字を読める形に直す(日時・UID など) |
-c httpd |
コマンド名で絞る |
-if ファイル |
別のマシンから持ってきたログファイルを読む |
-i の有無で、時刻の表し方が変わります。Red Hat のドキュメントにある AVC の行をファイルに保存して ausearch -if で読んだ結果です(-i を付けた方は、手元のタイムゾーンの日時になります)。
$ ausearch -m AVC -if avc.log -i
----
type=AVC msg=audit(11/17/08 07:21:13.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
3. ログが出ないのに怪しいとき:dontaudit
ポリシーには「止めるが、ログに残さない」ルール(dontaudit)があります。 Red Hat のドキュメントでは、ログが出ないときは dontaudit を一時的に外して再現する手順が載っています。
sudo semodule -DB # dontaudit を外してポリシーを作り直す
# ……問題を再現して ausearch で探す……
sudo semodule -B # 元に戻す
4. Permissive にして再現する(確かめるだけ)
sudo setenforce 0 # Permissive(再起動で元に戻る)
# ……再現する……
sudo setenforce 1 # Enforcing に戻す
Red Hat のドキュメントでは、Permissive で問題がまだ起きるなら、SELinux 以外が止めていると判断します。Permissive で直ったら、それは「原因が SELinux だと分かった」だけなので、すぐ Enforcing に戻してから、この記事の手順で直します。
AVC ログの読み方
Red Hat のドキュメントにある例です(1行のログを、読みやすいように区切っています)。
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
| 項目 | 例 | 読み方 |
|---|---|---|
msg=audit(...) |
1226874073.147:96 |
UNIX 時刻(秒)と通し番号。ausearch -i で日時になる |
avc: denied |
― | 止めた。granted なら許可(記録だけ) |
{ ... } |
{ getattr } |
止められた操作。read・write・open・getattr・name_bind・name_connect など |
pid / comm |
2465 / httpd |
操作したプロセス |
path / name |
/var/www/html/file1 |
対象のファイル(name はファイル名だけのことがある) |
scontext |
...:httpd_t:s0 |
操作した側のラベル。3つ目の httpd_t が「ドメイン」 |
tcontext |
...:samba_share_t:s0 |
操作された側のラベル。3つ目の samba_share_t が「タイプ」 |
tclass |
file |
対象の種類。dir・tcp_socket・sock_file など |
permissive |
0 / 1 |
1 は Permissive なので、実際には止めていない |
見るのは scontext と tcontext の3つ目(タイプ)です。 この例は、「Web サーバー(httpd_t)が、Samba 用のラベル(samba_share_t)が付いたファイルを読もうとして止められた」という意味です。/var/www/html の下なのに samba_share_t が付いているので、ラベルの付け間違いと分かります。
よくある組み合わせ
| scontext → tcontext | 操作 | よくある原因 | 直し方 |
|---|---|---|---|
httpd_t → user_home_t |
read・getattr |
ホームで作ったファイルを mv した |
restorecon -Rv /var/www/html |
httpd_t → default_t・var_t |
read |
/srv/web など、標準でない場所に置いた |
semanage fcontext -a + restorecon |
httpd_t → httpd_sys_content_t |
write |
アップロード先に書き込めない | 書き込む場所だけ httpd_sys_rw_content_t |
httpd_t → port_t(tcp_socket) |
name_bind |
標準でないポートで待ち受け | semanage port -a -t http_port_t |
httpd_t → mysqld_port_t など |
name_connect |
PHP などから DB・API につなぐ | setsebool -P httpd_can_network_connect_db on |
httpd_t → nfs_t |
read |
NFS 上のファイルを配信 | setsebool -P httpd_use_nfs on |
container_t → user_home_t |
read |
コンテナにホストのディレクトリをマウント | Podman・Docker の :Z / :z |
sealert で原因の候補を見る
sealert は、AVC ログを読んで「何が起きたか」と「直し方の候補」を文章にするツールです。 setroubleshoot-server のパッケージに入っています。
sudo dnf install setroubleshoot-server
sudo sealert -l "*" # 記録されたものを全部
sudo sealert -a /var/log/audit/audit.log # ログファイルを読む
Red Hat のドキュメントにある出力の一部です。
SELinux is preventing /usr/bin/passwd from write access on the file /root/test.
***** Plugin leaks (86.2 confidence) suggests *****************************
...
***** Plugin catchall (14.7 confidence) suggests **************************
候補は「確からしさ(confidence)」の高い順に出ます。 restorecon や setsebool を勧める候補があれば、それを先に検討します。最後の方に出る catchall(audit2allow で許可ルールを作る案)は、他に当てはまらないときの案です。
直し方1:ラベル(ファイルコンテキスト)
SELinux は、ファイルに付いた「ラベル」で読み書きを決めます。 パーミッションが 644 でも、Web サーバーが読めるラベルでなければ読めません。
ls -Z /var/www/html/index.html # ファイルのラベルを見る
ps -eZ | grep httpd # プロセスのラベルを見る
matchpathcon /var/www/html/index.html # 「本来付くべき」ラベル
$ matchpathcon /var/www/html/index.html /srv/www/a
/var/www/html/index.html system_u:object_r:httpd_sys_content_t:s0
/srv/www/a system_u:object_r:httpd_sys_content_t:s0
mv と cp でラベルが変わる
| 操作 | ラベル |
|---|---|
cp a.html /var/www/html/ |
コピー先の規則で新しく付く(httpd_sys_content_t) |
mv ~/a.html /var/www/html/ |
元のラベルのまま(user_home_t)→ 読めない |
cp -a・cp --preserve=context |
元のラベルを持っていく |
tar・rsync で展開 |
オプションによって元のラベルを持ってくる |
mv で置いたファイルが読めないときは、restorecon で本来のラベルに戻します。
sudo restorecon -Rv /var/www/html # -R:下まで、-v:変えたものを表示
sudo restorecon -Rnv /var/www/html # -n:変えずに「変わるもの」だけ表示
標準でない場所を使う:semanage fcontext
/srv/myweb のような場所は、まず「この場所にはこのラベル」という規則を登録してから、restorecon で付けます。 規則を登録しただけでは、ファイルのラベルは変わりません。
sudo semanage fcontext -a -t httpd_sys_content_t '/srv/myweb(/.*)?'
sudo restorecon -Rv /srv/myweb
Ubuntu のポリシーで登録して、matchpathcon で確かめた結果です。
$ matchpathcon /srv/myweb/index.html # 登録前
/srv/myweb/index.html system_u:object_r:var_t:s0
$ sudo semanage fcontext -a -t httpd_sys_content_t '/srv/myweb(/.*)?'
$ sudo semanage fcontext -l -C # 自分で足した規則だけ表示
SELinux fcontext type Context
/srv/myweb(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
$ matchpathcon /srv/myweb/index.html # 登録後
/srv/myweb/index.html system_u:object_r:httpd_sys_content_t:s0
'/srv/myweb(/.*)?' は正規表現で、「/srv/myweb そのものと、その下のすべて」です。 引用符で囲まないと、シェルが ( を解釈してエラーになります。
「既にある場所と同じ規則にしたい」ときは、-e(同じ扱いにする)が使えます。Red Hat のドキュメントでは、/var/test_www を /var/www と同じ扱いにする例が載っています。
sudo semanage fcontext -a -e /var/www /var/test_www
sudo restorecon -Rv /var/test_www
Web サーバーで使う主なタイプ
| タイプ | 用途 |
|---|---|
httpd_sys_content_t |
読むだけのコンテンツ(HTML・画像) |
httpd_sys_rw_content_t |
読み書きするもの(アップロード先・キャッシュ・wp-content) |
httpd_sys_ra_content_t |
追記だけするもの(ログなど) |
httpd_sys_script_exec_t |
CGI スクリプト |
httpd_log_t |
Web サーバーのログ |
public_content_t |
FTP・Samba・Web で共有する読み取り用 |
Fedora・RHEL のポリシーのソース(apache.fc)では、/var/www/html(/.*)?/wp-content(/.*)?・/var/www/html(/.*)?/uploads(/.*)? などに最初から httpd_sys_rw_content_t が割り当てられています。/var/www/html 全体を httpd_sys_rw_content_t にすると、Web サーバーがどこにでも書き込めるようになります。 書き込む場所だけに付けます。
chcon との違い
chcon はファイルのラベルを直接書き換えますが、規則には残りません。 restorecon を実行したときや、システム全体のラベルの付け直し(relabel)のときに、規則どおりのラベルに戻ります。
| 方法 | 変えるもの | restorecon・relabel のあと |
|---|---|---|
chcon -t httpd_sys_content_t file |
ファイルのラベルだけ | 規則のラベルに戻る |
semanage fcontext -a + restorecon |
規則とファイルのラベル | 残る |
sudo chcon -R -t httpd_sys_content_t /srv/test # 一時的に試すとき
sudo chcon --reference=/var/www/html /srv/test # 他のファイルと同じラベルにする
chcon は「このラベルで直るか」を試すのに使い、直ると分かったら semanage fcontext で規則にします。
直し方2:boolean(スイッチ)
boolean は、ポリシーにあらかじめ用意された「この動きを許すか」のスイッチです。 よくある用途のためのルールが、最初から off で入っています。
getsebool -a | grep httpd # httpd の boolean と今の値
sudo semanage boolean -l | grep httpd # 説明つき(今の値, 既定値)
sudo setsebool -P httpd_can_network_connect_db on
-P を付けないと、再起動で元に戻ります。 setsebool の man ページでは、-P なしは「今の値だけ」を変え、-P を付けると「ディスク上のポリシーに書き込まれ、再起動後も残る」と説明されています。
主な boolean 一覧
Fedora・RHEL のポリシーのソースから、説明(原文)と既定値を抜き出しました。既定値は、targeted ポリシー用の設定(dist/targeted/booleans.conf)で上書きされているものを反映しています。
| boolean | 既定値 | 説明(ポリシーのソースより) |
|---|---|---|
httpd_can_network_connect |
off | Allow HTTPD scripts and modules to connect to the network using TCP. |
httpd_can_network_connect_db |
off | Allow HTTPD scripts and modules to connect to databases over the network. |
httpd_can_network_relay |
off | Allow httpd to act as a relay |
httpd_can_network_memcache |
off | Allow httpd to connect to memcache server |
httpd_can_sendmail |
off | Allow http daemon to send mail |
httpd_can_connect_ftp |
off | Allow httpd to act as a FTP client connecting to the ftp port and ephemeral ports |
httpd_enable_homedirs |
off | Allow httpd to read home directories |
httpd_read_user_content |
off | Allow httpd to read user content |
httpd_use_nfs |
off | Allow httpd to access nfs file systems |
httpd_use_cifs |
off | Allow httpd to access cifs file systems |
httpd_use_fusefs |
off | Allow httpd to access FUSE file systems |
httpd_execmem |
off | Allow httpd scripts and modules execmem/execstack |
httpd_unified |
off | Unify HTTPD handling of all content files. |
httpd_setrlimit |
off | Allow httpd daemon to change its resource limits |
httpd_tmp_exec |
off | Allow Apache to execute tmp content. |
httpd_enable_cgi |
on | Allow httpd cgi support |
httpd_builtin_scripting |
on | Allow httpd to use built in scripting (usually php) |
httpd_anon_write |
off | Allow Apache to modify public files used for public file transfer services. |
ftpd_full_access |
off | Determine whether ftpd can login to local users and can read and write all files on the system, governed by DAC. |
ftpd_use_passive_mode |
off | Determine whether ftpd can bind to all unreserved ports for passive mode. |
samba_enable_home_dirs |
off | Allow samba and winbind-rpcd to share users home directories. |
samba_export_all_ro |
off | Allow samba to share any file/directory read only. |
samba_export_all_rw |
off | Allow samba to share any file/directory read/write. |
use_nfs_home_dirs |
off | Support NFS home directories |
nis_enabled |
off | Allow system to run with NIS |
virt_use_nfs |
off | Allow confined virtual guests to manage nfs files |
rsync_full_access |
off | Allow rsync server to manage all files/directories on the system. |
named_write_master_zones |
on | Determine whether Bind can write to master zone files. |
httpd_can_network_connect は範囲が広い
httpd_can_network_connect は、Web サーバーから「どのポートへの接続も」許します。 DB だけなら httpd_can_network_connect_db のように、狭い boolean を選びます。Ubuntu のポリシーを sesearch(ポリシーのルールを検索するツール)で調べた結果です(RHEL のポリシーとはルールの細部が違います)。
$ sesearch -A -s httpd_t -c tcp_socket -p name_connect policy.33
allow httpd_t mysqld_port_t:tcp_socket name_connect; [ httpd_can_network_connect_db ]:True
allow httpd_t postgresql_port_t:tcp_socket name_connect; [ httpd_can_network_connect_db ]:True
allow httpd_t oracledb_port_t:tcp_socket name_connect; [ httpd_can_network_connect_db ]:True
allow httpd_t memcache_port_t:tcp_socket name_connect; [ httpd_can_network_connect_memcache ]:True
allow httpd_t smtp_port_t:tcp_socket name_connect; [ httpd_can_sendmail ]:True
allow httpd_t port_type:tcp_socket name_connect; [ httpd_can_network_connect ]:True
...
| boolean | つながる先(Ubuntu のポリシーで確かめたもの) |
|---|---|
httpd_can_network_connect_db |
mysqld_port_t・postgresql_port_t・oracledb_port_t・mssql_port_t・gds_db_port_t |
httpd_can_network_connect_memcache |
memcache_port_t |
httpd_can_sendmail |
smtp_port_t・pop_port_t |
httpd_can_network_relay |
http_port_t・http_cache_port_t・ftp_port_t・squid_port_t・gopher_port_t |
httpd_can_network_connect |
port_type(ラベルが付いたポートすべて) |
nginx・Apache をリバースプロキシにして、バックエンドの 8080 番などへ転送するときは、httpd_can_network_connect を on にする手順がよく紹介されます。プロキシの設定は、関連記事「Nginxリバースプロキシ設定|proxy_passの書き方と502/504対処」で扱っています。
直し方3:ポートのラベル(semanage port)
SELinux は、ポート番号にもラベルを付けています。 Web サーバー(httpd_t)は http_port_t のポートでしか待ち受けられません。Fedora・RHEL のポリシーのソース(corenetwork.te.in)での割り当てです。
| タイプ | ポート(TCP) | 使うもの |
|---|---|---|
http_port_t |
80, 81, 443, 488, 8008, 8009, 8443, 9000 | Apache・nginx |
http_cache_port_t |
8080, 8118, 8123, 10001-10010 | プロキシ・キャッシュ |
ssh_port_t |
22 | sshd |
mysqld_port_t |
1186, 3306, 63132-63164 | MySQL・MariaDB |
postgresql_port_t |
5432, 9898 | PostgreSQL |
redis_port_t |
6379, 16379, 26379 | Redis |
mongod_port_t |
27017-27019, 28017-28019 | MongoDB |
smtp_port_t |
25, 465, 587 | メール |
ラベルが付いていないポートは port_t、または別のサービス用のタイプです。 Apache を 9876 番で起動しようとすると、Red Hat のドキュメントの例のように name_bind が止められます。
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
sudo semanage port -l | grep -w http_port_t # 今の割り当て
sudo semanage port -a -t http_port_t -p tcp 9876 # 追加
sudo semanage port -l -C # 自分で足したものだけ
sudo semanage port -d -t http_port_t -p tcp 9876 # 削除
Ubuntu のポリシーで追加した結果です。
$ sudo semanage port -a -t http_port_t -p tcp 9876
$ sudo semanage port -l | grep ^http_port_t
http_port_t tcp 9876, 8080, 80, 443, 488, 8008, 8009, 8443, 8448
$ sudo semanage port -l -C
SELinux Port Type Proto Port Number
http_port_t tcp 8080, 9876
「already defined」は -m で変える
8080 番のように、既に別のタイプが付いているポートに -a を使うとエラーになります。
$ sudo semanage port -a -t http_port_t -p tcp 8080
ValueError: Port tcp/8080 already defined
$ sudo semanage port -m -t http_port_t -p tcp 8080 # -m(変更)なら通る
SSH のポートを変えるときも同じで、semanage port -a -t ssh_port_t -p tcp 2222 を先に行ってから sshd の設定を変えます。ファイアウォールの穴あけも別に要ります。手順は関連記事「ufwとfirewalldの使い方|コマンド対応表とSSH締め出し対策」で扱っています。ポートを使っているプロセスの調べ方は、関連記事「ポートを使っているプロセスの調べ方|ss・lsof・netstat比較」で扱っています。
audit2allow の使い方と注意
audit2allow は、AVC ログから「これを許すルール」を作るツールです。 便利ですが、Red Hat のドキュメントでは「SELinux の拒否を見たとき、最初の選択肢として audit2allow でローカルのポリシーモジュールを作るべきではない」と書かれ、まずラベルの問題かを確かめるよう案内されています。
実際に作られるルールを見る
この記事で使った Red Hat の AVC の例2行(Samba のラベルのファイルを読む・9876 番で待ち受ける)を、そのまま audit2allow に通した結果です(Ubuntu のポリシーで解析)。
$ audit2allow -i avc.log
#============= httpd_t ==============
#!!!! This avc can be allowed using the boolean 'allow_ypbind'
allow httpd_t port_t:tcp_socket name_bind;
allow httpd_t samba_share_t:file getattr;
どちらも、望ましい直し方ではありません。
| audit2allow の案 | 起きること | 本来の直し方 |
|---|---|---|
allow httpd_t port_t:tcp_socket name_bind; |
ラベルの無いすべてのポートで Web サーバーが待ち受けられる | semanage port -a -t http_port_t -p tcp 9876 |
allow httpd_t samba_share_t:file getattr; |
Web サーバーが Samba の共有ファイル全部を調べられる | restorecon でラベルを直す |
boolean allow_ypbind(RHEL では nis_enabled)を on |
NIS 用のスイッチ。Ubuntu のポリシーでは、この boolean で有効になるルールが 2,969 件あった(sesearch -A -b allow_ypbind の行数) |
使わない |
-w(audit2why と同じ)を付けると、理由の説明が出ます。
$ audit2allow -w -i avc.log
type=AVC msg=audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd" path="/var/www/html/file1" ...
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
「許可ルールが無い」と出ても、それは「今のラベルのままなら許可ルールが要る」という意味で、ラベルが正しいかどうかは教えてくれません。audit2allow の man ページにも、「出力をそのまま入れるのではなく、許す操作がセキュリティ上の脅威にならないかを確かめる」「拒否されても動作に支障がないものは、dontaudit で記録だけ止める方が望ましいことがある」と書かれています。
それでもモジュールを作るとき
ラベル・boolean・ポートのどれでも直らず、許す範囲が狭いと確かめられたときの手順です。
sudo ausearch -m AVC -c myapp --raw | audit2allow -M myapp_local # myapp に関係する行だけ
cat myapp_local.te # 中身を必ず読む
sudo semodule -i myapp_local.pp # 読み込む
sudo semodule -l | grep myapp_local # 入ったか
sudo semodule -r myapp_local # 外す
-M を付けると、.te(ルールの文章)と .pp(読み込む形)の2つができます。手元で作った .te はこの形でした。
module mywebfix 1.0;
require {
type httpd_t;
type port_t;
type samba_share_t;
class file getattr;
class tcp_socket name_bind;
}
#============= httpd_t ==============
#!!!! This avc can be allowed using the boolean 'allow_ypbind'
allow httpd_t port_t:tcp_socket name_bind;
allow httpd_t samba_share_t:file getattr;
ausearch で絞らずに audit.log 全体を通すと、関係ないプロセスの拒否まで許してしまいます。 -c(コマンド名)や -ts(時刻)で絞ってから通します。
setenforce 0 で済ませない理由
| やり方 | 影響する範囲 | 再起動後 |
|---|---|---|
setenforce 0 |
システム全体が Permissive | Enforcing に戻る(設定ファイルが enforcing なら) |
/etc/selinux/config を SELINUX=permissive |
システム全体 | Permissive のまま |
SELINUX=disabled・カーネルの selinux=0 |
システム全体で無効。ラベルも付かない | 無効のまま |
semanage permissive -a httpd_t |
httpd_t だけ Permissive | 残る(-d で戻す) |
| boolean・ラベル・ポートを直す | 必要な操作だけ | 残る |
Permissive や無効にすると、Web サーバーが乗っ取られたときに、ほかのファイルやサービスへ広がるのを止める仕組みが無くなります。 Red Hat のドキュメントでは、性能が重視されるような特定の場面以外は SELinux を無効にしないこと、本番で調べるときは一時的に Permissive を使うことが書かれています。
一度無効にしたあと有効に戻すときは、ファイルのラベルを付け直す必要があります。 無効の間に作られたファイルにはラベルが付いていないためです。Red Hat のドキュメントでは、fixfiles -F onboot で次の起動時に付け直す手順になっています。
sudo fixfiles -F onboot # /.autorelabel を作る。次の起動で全体のラベルを付け直す
sudo reboot
1つのサービスだけを調べたいときは、そのドメインだけを Permissive にします。
sudo semanage permissive -a httpd_t # httpd_t だけ Permissive
sudo semanage permissive -l # 一覧
sudo semanage permissive -d httpd_t # 戻す
コンテナのマウントで Permission denied
Podman・Docker でホストのディレクトリをマウントすると、コンテナ(container_t)から読めないことがあります。 ボリュームに :Z か :z を付けると、マウントするときにラベルを付け直します。
podman run -v ./data:/data:Z myimage # このコンテナ専用のラベル
podman run -v ./data:/data:z myimage # 複数のコンテナで共有するラベル
Podman のドキュメントでは、z・Z は relabel=shared・relabel=private の短縮形で、マウントの中を再帰的にたどってラベルを付ける、と説明されています。/home や /usr のようなシステムのディレクトリに付けると、そこ全体のラベルが変わります。 プロジェクトのディレクトリだけに付けます。Docker の bind mount の権限の問題は、関連記事「Docker bind mountのPermission deniedの直し方」で扱っています。
よくある質問
Q. chmod 777 にしても Permission denied です。
A. パーミッション(DAC)と SELinux(MAC)は別々に判定され、両方で許されたときだけ読み書きできます。ausearch -m AVC に行があれば SELinux です。パーミッションの意味は、関連記事「chmodの755と644の意味|用途別パーミッション早見表」で扱っています。
Q. ausearch で <no matches> と出ます。
A. -ts recent は直近10分です。-ts today に広げます。それでも無ければ、systemctl status auditd で auditd が動いているかを見て、dontaudit(semodule -DB)を疑います。
Q. semanage: command not found と出ます。
A. RHEL・Fedora 系では policycoreutils-python-utils のパッケージに入っています。sealert は setroubleshoot-server、ausearch は audit のパッケージです。
Q. boolean の名前が分かりません。
A. getsebool -a | grep キーワード、説明つきなら semanage boolean -l | grep キーワード で探します。sealert の候補にも boolean の名前が出ます。
Q. ログの調べ方をもっと知りたいです。
A. setroubleshoot の要約は journald に入るので、journalctl -t setroubleshoot で読めます。journalctl の絞り込みは、関連記事「journalctlの使い方|目的別コマンド逆引き一覧と絞り込み例」で扱っています。
まとめ
getenforceが Enforcing なら、ausearch -m AVC -ts recent -iで拒否ログを探す。出なければsemodule -DB- AVC は
scontextとtcontextの3つ目(タイプ) と、{ }の中の操作を見る - 直し方は ラベル → boolean → ポート の順に考える
- 標準でない場所は
semanage fcontext -a+restorecon -Rv。chconはrestoreconで戻る - boolean は
-Pを付けないと再起動で戻る。httpd_can_network_connectより狭いものがあればそちら - ポートは
semanage port -a、既にタイプがあれば-m - audit2allow の案は広すぎることがある。 実際に、ポートとラベルの問題に「全部許す」ルールが作られた
setenforce 0は原因の確認だけ。サービス単位ならsemanage permissive -a
参考・出典
確認日はいずれも 2026年10月13日です。
- Red Hat「Using SELinux(RHEL 9)- Troubleshooting problems related to SELinux」:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux/troubleshooting-problems-related-to-selinux_using-selinux
- Red Hat「Using SELinux(RHEL 9)- Configuring SELinux for applications and services with non-standard configurations」:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux/configuring-selinux-for-applications-and-services-with-non-standard-configurations_using-selinux
- Red Hat「Using SELinux(RHEL 9)- Changing SELinux states and modes」:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux/changing-selinux-states-and-modes_using-selinux
- Red Hat「Basic SELinux Troubleshooting in CLI」:https://access.redhat.com/articles/2191331
- fedora-selinux/selinux-policy(apache.te・apache.fc・corenetwork.te.in・dist/targeted/booleans.conf):https://github.com/fedora-selinux/selinux-policy
- SELinuxProject/selinux(audit2allow・semanage-fcontext・semanage-port・semanage-permissive・setsebool・setenforce の man ページ):https://github.com/SELinuxProject/selinux
- restorecon(8) — Linux manual page:https://man7.org/linux/man-pages/man8/restorecon.8.html
- chcon(1) — Linux manual page:https://man7.org/linux/man-pages/man1/chcon.1.html
- Podman「podman-run」:https://docs.podman.io/en/latest/markdown/podman-run.1.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「SELinuxでPermission deniedになる原因|確かめ方と直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。