パーミッション(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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?