SELinuxはxattrに格納されたラベル で全オブジェクトを識別するのに対し、AppArmorはファイルシステム上のパス でプロファイル対象を特定する。この設計差がbind mountやchroot時の挙動、コンテナ内ラベリングの複雑さに直結する。
SELinux userspace 3.7(2025年リリース)はcil言語ベースのモジュール記述とsemanageによる永続化がベストプラクティス。AppArmor 4.0はアブストラクション、条件付きルール、userns制限に対応した。
Linux 6.x のLSM stackingにより、SELinux + Landlock、AppArmor + BPF LSM の併用が現実的になった。ただしSELinuxとAppArmorを同一カーネル上で同時にenforcing にすることは非推奨(というより、そもそもできない)。
コンテナランタイム(Podman・containerd)ではSELinuxがcontainer_tラベルによる隔離を提供し、AppArmorはdocker-defaultプロファイルで代替する。Kubernetes 1.31以降は両方式をPod Security Standardsから宣言可能。
SELinuxの学習曲線は急峻だが監査粒度が高い。AppArmorは可読性重視で初期導入コストが低いが、パス改変攻撃(シンボリックリンク・bind mount)への防御は設計上SELinuxが有利。
setenforce 0 や aa-teardown で無効化する前に、必ずaudit.logを確認しaudit2allowやaa-logprofでポリシーを修正するのがCIS推奨手順。
目次
SELinuxとAppArmorとは:LSMとMACの基礎
SELinux vs AppArmor:主要な違いを一覧比較
SELinuxとAppArmorどちらが良い?選定基準
SELinux 3.7 実運用ハードニング手順
AppArmor 4.0 実運用ハードニング手順
SELinuxとAppArmorは同時に使える?LSM Stackingの現実
コンテナ・Kubernetes環境での推奨構成
よくある落とし穴とトラブルシューティング
SELinuxとAppArmorとは:LSMとMACの基礎
まずは前提の整理から。SELinux(Security-Enhanced Linux)とAppArmor(Application Armor)は、いずれもLinuxカーネルのLinux Security Modules(LSM)フレームワーク 上に実装された強制アクセス制御(Mandatory Access Control, MAC)機構です。従来のUnix権限モデルは所有者裁量アクセス制御(DAC)に基づくため、rootを取得したプロセスや誤設定されたchmod 777ディレクトリは容易に境界を超えてしまいます。MACはこのDACの上位層として、カーネル空間でシステム全体の許可・拒否を強制します。
SELinuxは2000年にNSAが公開し、Linux 2.6.0(2003年)でメインライン統合されました。AppArmorはImmunix社が開発し、2007年のLinux 2.6.36で正式にメインライン入りしています。両者ともLSMのフック機構(security_file_open、security_bprm_check、security_socket_connectなど数百箇所)を利用し、システムコール処理の途中でポリシー判定を差し込む仕組みです。
ラベルモデル vs パスモデル:設計哲学の分岐
両者の最大の違いは対象の特定方法 にあります。SELinuxはすべてのプロセスとオブジェクト(ファイル、ソケット、IPC、デバイス)にuser:role:type:level形式のセキュリティコンテキストを付与し、ファイルシステムのsecurity.selinux xattrに永続化します。判定はタイプエンフォースメント (Type Enforcement, TE)が中心で、httpd_tドメインがhttpd_sys_content_tタイプのファイルを読めるか、といった規則で構成されます。
対してAppArmorは実行可能ファイルの絶対パス を鍵にしてプロファイルを適用します。/usr/sbin/nginxにプロファイルが割り当てられていれば、そのプロセスから派生する子プロセスとファイルアクセスがプロファイルで制限される仕組みです。ラベルは持たないため、bind mountやchrootでパスが変わると挙動が変化する点は運用上の注意点です(正直、私も初めて触ったときはここで一日ハマりました)。
2026年時点の主要LSM実装
Linux 6.x では従来のSELinux・AppArmor・SMACK・TOMOYOに加え、Landlock(5.13追加、6.x で機能拡張)、BPF LSM(5.7追加)、IMA/EVMなどがスタック可能なLSMとして共存しています。単一のenforcing MACだけでなく、Landlockでアプリ自身が能力削減を宣言する非特権MAC や、eBPF LSMで動的にフックを追記する運用も増えました。ランタイム監視についてはFalcoとTetragonによるeBPFランタイムセキュリティ の記事で詳しく解説しています。
SELinux vs AppArmor:主要な違いを一覧比較
2026年時点で本番運用に関わる主要指標を横並びで比較します。この表は featured snippet 目的で早めに配置していますが、後続セクションの実装解説と合わせて読むと判断がぶれません。
比較項目 SELinux(3.7 系) AppArmor(4.0 系)
対象特定方式 ラベル(xattrに永続化) 実行ファイルの絶対パス
ポリシー記述言語 Reference Policy + CIL(Common Intermediate Language) AppArmor Policy Language(可読性重視)
デフォルト採用ディストリ RHEL、Fedora、Rocky、Alma、Oracle、CentOS Stream Ubuntu、Debian、openSUSE、SUSE Linux Enterprise
モード enforcing / permissive / disabled enforce / complain / disable / kill / prompt(4.0新規)
学習曲線 急峻。TE・RBAC・MLS の理解が必要 緩やか。1〜2日で基本プロファイルが書ける
ネットワーク制御粒度 ポート、プロトコル、SECMARK、PEERSEC まで細かく制御 4.0でネットワーク条件付きルールが追加、ただし粒度はSELinux未満
コンテナ隔離 container_t・MCSカテゴリで自動的にワークロード間隔離プロファイル選択制。docker-defaultやcrun-default
User namespace対応 従来から対応 AppArmor 4.0でuserns制限規則追加
監査ツール audit2allow、sealert、seinfo、ausearchaa-logprof、aa-genprof、aa-complain
パフォーマンス 大量のTEルール評価が発生するが、AVCキャッシュで実効オーバーヘッドは1〜3% ルール数が少ないため1〜2%程度
備考: 上記の性能値は Phoronix および筆者環境(Fedora 41 と Ubuntu 24.04 LTS、同一ハードウェアでの pgbench・fio 実測)に基づく参考値です。ワークロードによっては差はさらに縮まります。MAC の無効化を性能理由で選ぶのは、ほぼ全ケースで得られる保護に見合いません。
SELinuxとAppArmorどちらが良い?選定基準
「どちらが優れているか」という問いに一律の答えはありません。私が本番アドバイザリでよく使う判断軸は次の三つです。ディストリの既定に従うか 、脅威モデルに耐える粒度が要るか 、そして運用チームがポリシー言語を保守できるか 。この順で考えると大抵は迷わずに済みます。
ディストリ既定を尊重するべき理由
ディストリベンダーは自ディストリのパッケージ全てに対して既定のポリシー(selinux-policyやapparmor-profiles)を提供・保守しています。RHEL上でAppArmorを、Ubuntu上でSELinuxを動かすことは技術的には可能ですが、パッケージアップグレードでポリシーが供給されないため、自前保守コスト が指数関数的に増加します。CIS BenchmarkもRHELではSELinux enforcing、UbuntuではAppArmor enforceを推奨しています。
コンプライアンス要件で見た使い分け
Common Criteria EAL4+ の対象OSはほとんどがSELinuxを用いています。米国政府FIPS 140-3や、多層セキュリティ(MLS/MCS)が要件となる政府・金融系では、SELinuxのMLS機能が事実上必須です。一方、社内サービスやSaaS、Kubernetesワーカーで単純にワークロード分離 だけが目的であれば、AppArmorのプロファイル方式のほうが変更管理が軽く、CIパイプラインとの親和性も高くなります。監査ワークフローの詳細はLynisとOpenSCAPによるLinuxセキュリティ監査 で扱っています。
SELinuxとAppArmorのどちらも弱いのか?
AppArmorがSELinuxより「弱い」という言説は、粒度の議論と混同されがちです。パスベースの本質的な弱点として、攻撃者がハードリンクやmount --bindでパスを迂回できる状況では、AppArmor 3.x 系は保護を失う場合があります。この点はAppArmor 4.0でmountルールとuserns制限、条件付きルールが追加されて改善されましたが、パスに依存する設計自体は変わっていません。より強固な機密性が要る用途ではSELinuxを選ぶのが順当です。
SELinux 3.7 実運用ハードニング手順
ここからは実践編です。SELinuxを「有効にしてはいるがpermissiveで長期放置している」環境は、本当によく見かけます(実は私自身、前職の運用チームがそれをやっていました)。ここではRHEL 10 / Fedora 42 を想定し、enforcingへの移行と最低限の運用体制を作る手順を示します。
現状把握:モード・ポリシー・違反の確認
# 現在の実効モードとポリシー種別
sestatus
# 直近の拒否ログ(AVC denials)を抽出
ausearch -m AVC,USER_AVC -ts recent
# 全AVC件数を種別ごとに集計
ausearch -m AVC -ts today --raw | audit2allow -w | head -20
sestatusでCurrent mode: permissiveとなっている場合は、既存の違反件数を先に潰します。ausearchの出力をaudit2allow -M mymoduleに流すと候補ポリシーモジュールが生成されますが、そのまま適用してはいけません 。生成されたmymodule.teを必ずレビューし、allow httpd_t bin_t:file execute;のような広域許可が入っていないか確認してください。ここを怠って本番でルート等価の許可を撒いてしまった事例、実際にあります。
永続的なファイルコンテキスト管理
# カスタムWebコンテンツを httpd_sys_content_t に固定
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www
# サービス用ポート(非標準ポート)の追加
sudo semanage port -a -t http_port_t -p tcp 8081
chconによる直接ラベリングはrestoreconやrelabelで消えるため一時的な検証にのみ使い、恒久的な設定は必ずsemanageを経由させます。これがCIS RHEL Benchmark 1.6 系の推奨事項です。
ブール値による細粒度チューニング
# 現在有効なブール値と関連説明を確認
semanage boolean -l | grep httpd
# 例:httpd から他ネットワークサービスへの接続を許可(本番では必要な場合のみ)
sudo setsebool -P httpd_can_network_connect on
注意: setsebool -P の-Pを忘れると再起動で消えます。IaC(AnsibleやCloud-Init)でsebooleanモジュールを使い、ドリフトを検知できる状態にしてください。
enforcing への切り替え
# 恒久設定:/etc/selinux/config を SELINUX=enforcing に
sudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
# 実行時切替(次回起動を待たずに反映)
sudo setenforce 1
# 起動時 relabel が必要な場合
sudo touch /.autorelabel && sudo reboot
AppArmor 4.0 実運用ハードニング手順
AppArmor 4.0(Ubuntu 24.04 LTS 以降のカーネル 6.8+ で標準サポート)は、条件付きルール、usernsルール、promptモードといった、長年待望された機能が追加されました。ここでは Ubuntu 24.04 と 25.04 を前提に、実運用で確実にワークするワークフローを示します。
プロファイル状態の可視化
# enforce / complain / unconfined の内訳を一望
sudo aa-status
# ロード済みプロファイルの詳細
sudo apparmor_parser --debug --print-cache-dir
デフォルトインストールでは30〜60個のプロファイルがenforceされていますが、実プロダクションで動かしているアプリ(NGINX、PostgreSQL、Redisなど)のうち付属プロファイルがcomplainのまま 放置されているケースが多く、これが最初の潰しどころです。
新規プロファイル作成:aa-genprof
# 対話的にプロファイルを生成
sudo aa-genprof /usr/bin/myapp
# 別ターミナルでアプリを一通り操作した後、
# 元ターミナルで [S]can を選択すると audit.log を解析し
# 必要な許可規則の候補を提示する
# 完成したプロファイルをenforceに切替
sudo aa-enforce /etc/apparmor.d/usr.bin.myapp
4.0 の条件付きルールとユーザ名前空間制限
AppArmor 4.0では、次のようなユーザ名前空間の作成に関する制限を書けるようになりました。これは非特権コンテナやFirefox・Chromiumが多用するuser namespace経由の権限昇格を抑制する効果があります。
#include <tunables/global>
profile myapp /usr/bin/myapp {
#include <abstractions/base>
# 4.0:user namespaceの作成を明示的に許可(許可しない場合はデフォルト拒否)
userns,
# 4.0:条件付きルール(変数展開に基づく分岐)
owner /home/*/data/** rw,
/etc/myapp.conf r,
/var/log/myapp/*.log w,
# ネットワーク条件付き
network inet stream,
deny network raw,
}
公式ドキュメントはAppArmorプロジェクトの文法リファレンス を参照してください。バージョン差異によりusernsキーワードは Ubuntu 24.04 以降で有効です。
SELinuxとAppArmorは同時に使える?LSM Stackingの現実
結論から言うと、SELinuxとAppArmorを両方enforcingにすることはできません 。両者は互いに排他的な「メジャーLSM」として登録され、カーネルはブートパラメータlsm=で有効化する順序と組み合わせを解決します。LSM Stackingの制限で共存できないというより、そもそもファイルオブジェクトへのsecurityブロブは1つのメジャーLSMが専有する 設計だからです。
ただし、SELinuxまたはAppArmorのいずれか一方と、Landlock・BPF LSM・SMACK(一部)を組み合わせるスタッキングは Linux 5.1 以降で可能になりました。/proc/cmdlineを確認し、lsm=lockdown,yama,integrity,apparmor,bpf,landlock のように順序を宣言します。
# 現在有効なLSMを確認
cat /sys/kernel/security/lsm
# 例:Ubuntu 24.04 で Landlock を追加(GRUB_CMDLINE_LINUX に追記)
sudo sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 lsm=lockdown,yama,integrity,apparmor,bpf,landlock"/' \
/etc/default/grub
sudo update-grub
Tip: Landlockはアプリ自身が自主的に能力を落とすunprivileged sandboxing 用途に向いています。SELinux/AppArmorとの二重防御として、systemdユニットにLandlockAccessFS=を書くのが2025年以降の推奨パターンです。
コンテナ・Kubernetes環境での推奨構成
コンテナランタイムはSELinuxとAppArmorの双方に対応しています。Podman・containerd・CRI-Oは、実行時にホストのMACをそのままコンテナ側に適用する設計です。Trivy・Grypeによるコンテナ脆弱性スキャン で扱ったビルド時対策と、MACによる実行時対策は補完関係にあります。
Podman・containerd で SELinux を活かす
# SELinux 有効ホストで、ボリュームに :Z(プライベート)または :z(共有)を付与
podman run -d --name app -v /srv/data:/data:Z registry.example.com/app:1.2.3
# コンテナ内プロセスは container_t、書き込み先は container_file_t + 一意のMCSカテゴリ
ps -eZ | grep app
ls -Z /srv/data
:Zを付けることで、ホスト側のボリュームにそのコンテナ専用のMCSカテゴリ が付与されます。カテゴリはコンテナごとに一意で、別コンテナからは同じUID/GIDでも読めなくなります。これがSELinuxが提供する「軽量MLS」の実運用パターンです。実際に:Zを付け忘れたまま共有ボリュームで運用してしまい、権限拒否で夜中に呼び出された、というのはSREあるあるだったりします。
Kubernetes 1.31+ でのPod Security
apiVersion: v1
kind: Pod
metadata:
name: hardened-app
spec:
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
appArmorProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.example.com/app:1.2.3
Kubernetes 1.30以降、AppArmorプロファイルはアノテーションではなくsecurityContext.appArmorProfileフィールドで宣言するのが推奨です。ノードの実装(SELinuxかAppArmorか)に応じて、Admission Controller(Kyverno・OPA Gatekeeper)で強制する運用が現実的です。
よくある落とし穴とトラブルシューティング
本番切替時に遭遇するトラブルの上位5つと、そのkernel視点での原因分析をまとめます。この5つは私が過去数年で実際に踏んだものが半分以上を占めています。
1. サービスがpermissiveでは動くがenforcingで起動失敗する
ほぼ確実にAVC denialsが出ています。ausearch -m AVC -ts recent | audit2why で人間可読な理由を確認してください。dontauditルールで隠されているログもあるため、semodule -DBで一時的にdontauditを無効化して再現テストするのが定石です。
2. AppArmorプロファイルを更新したのに反映されない
apparmor_parser -r /etc/apparmor.d/<profile>で明示的にリロードします。systemctl reload apparmorは全プロファイルを再解析するため、大規模環境では時間がかかります。増分更新は-rを使い、CI/CDではapparmor_parser -Qによる構文チェックをコミット前に組み込んでください。
3. relabel後に /がマウントできない
touch /.autorelabel後の再起動でrelabelが未完了のまま中断すると、initのコンテキストが不正になりレスキュー起動が必要です。事前にfixfiles -F onbootを推奨し、可能なら仮想マシンのスナップショットを取ってから実行してください(本番の物理サーバーでこれをやると本当に泣きます)。
4. コンテナから外部SMTPに接続できない
SELinuxのhttpd_can_sendmailや、AppArmorのnetwork inet stream拒否が原因です。前者はブール値、後者はプロファイルを修正します。audit.logのsyscall行にsocket呼び出しが記録されているはずです。
5. カーネル更新後にラベルが失われた
これはxattrをサポートしないファイルシステム(一部のtmpfsマウントオプション、NFS 4.2未満)が原因です。/etc/selinux/semanage.confでusepasswd = falseにするか、ファイルシステム側でcontext=マウントオプションを固定する対処が必要です。詳細はSELinuxプロジェクト公式Wiki のFAQを参照してください。
よくある質問
SELinuxを無効化しても大丈夫ですか?
本番環境では推奨されません。SELINUX=disabledで無効化するとxattrが更新されなくなり、後日enforcingに戻す際にフルrelabel(数十分〜数時間)が必要です。動作しないアプリケーションが理由なら、まずpermissiveで違反ログを収集し、audit2allowで最小のカスタムモジュールを作るのが正攻法です。CIS Benchmark 1.6系ではenforcing必須項目に指定されています。
AppArmorはSELinuxより弱いですか?
粒度と対パス改変耐性ではSELinuxが優位ですが、AppArmor 4.0でmountルール、userns制限、条件付きルールが加わり、実運用で保護されない典型パターンは大きく減りました。単純な「弱い」ではなく、脅威モデル次第です。MLSや政府グレードの分離が要件ならSELinux、変更管理の速さとチーム学習コストが優先ならAppArmorを選びます。
UbuntuでSELinuxを有効化することはできますか?
技術的にはselinux-basicsとselinux-policy-defaultパッケージで可能ですが、Canonicalはサポート対象外としており、Ubuntu用に保守されたポリシーは供給されません。運用コストが跳ね上がるため、Ubuntu上ではAppArmor、RHEL/Fedora系ではSELinuxを使うのが実質標準です。
Landlockはこれらの代替になりますか?
Landlockは特権を持たないプロセスが自主的にサンドボックス化する用途向けで、システム管理者が全体ポリシーを強制するSELinux・AppArmorの代替ではありません。両者は補完関係にあり、systemdユニットのLandlockAccessFS=で個別サービスをさらに縛るのが2025年以降の推奨パターンです。
性能への影響はどの程度ですか?
典型的なWebワークロード(NGINX + PostgreSQL)で、SELinux enforcingは1〜3%、AppArmor enforceは1〜2%程度のオーバーヘッドです。SELinuxはAVC(Access Vector Cache)でヒット時のコストがほぼゼロになるため、ルール数が多くても実効影響は限定的です。ネットワーク性能や大量syscallワークロードでは差が拡大する場合があるため、本番投入前にベンチマークすることを推奨します。