概要
SELinux (Security-Enhanced Linux) は、Linuxのセキュリティ拡張機能であり、強制アクセス制御 (MAC) の仕組みを提供する。 (Linux 2.6以降でサポート)
外部に侵入されないための仕組みではなく、侵入された後にアクセスできる範囲を最小限に抑えるための仕組みである。
SELinuxの特徴を以下に示す。
- 強制アクセス制御 (MAC)
- 従来の任意アクセス制御 (DAC) に加えて、より厳格なアクセス制御を実現する。
- 最小権限の原則
- プロセスやユーザに必要最小限の権限のみを与えることで、潜在的な被害を制限する。
- ポリシーベースの制御
- システム管理者が定義したセキュリティポリシーに基づいてアクセスを制御する。
- コンテキストラベル
- ファイル、プロセス、ポート等のリソースにセキュリティコンテキストを割り当てる。
- 動作モード
- Enforcing (強制)、Permissive (許容)、Disabled (無効) の3つのモードがある。
- ログ機能
- セキュリティ違反の試みを詳細にログに記録する。
| SELinuxの参考書 | |
|---|---|
SELinux System Administration 3rd Edition ソフトウェアやユーザ等を保護するための強制アクセス制御(MAC)の実装 |
SELinux Cookbook |
SELinuxの役割
SELinuxは、Linux上で動作するプロセスからファイル等のリソースに対するアクセスを制御するのが主な機能である。
通常のLinuxシステムでは、ユーザやグループのファイルに対するアクセス権で制御されますが、スーパーユーザは特権ユーザとして全てのファイル等にアクセスすることができる。
これに対して、SELinuxは"強制アクセス制御"(MAC: Mandatory Access Control)と呼ばれる方式を採用している。
MACは、スーパーユーザに対しても設定されたアクセス制御を超えた特権を与えることがない。
多くのセキュリティ攻撃がスーパーユーザ権限を奪取することを第一の目的とし、その後の攻撃に繋げていることを考えると、セキュリティ対策として必要な機能といえる。
SELinuxの機能
TE(Type Enforcement)
プロセスがアクセスできるリソースを制限する機能である。
プロセスにドメインを、リソースにタイプを割り当て、その組み合わせごとにアクセス権を設定する。
このアクセス権の設定の集合を、アクセスベクタという。
子プロセス生成時には、基本的には親プロセスのドメインが引き継がれる。
子プロセスのドメインを変更することを、ドメイン遷移と呼ぶ。
RBAC(Role Based Access Controle)
ユーザがアクセスできるリソースを制限する機能である。
ユーザごとにアクセス可能なロールが決まっており、ロールごとにアクセス可能なドメインが決まっている。
TEにより、ドメインごとにアクセス可能なタイプが決まっているため、最終的には、ユーザがアクセス可能なオブジェクトを制御することができる。
RHELでは、全てのLinuxユーザがunconfined_uに対応しており、unconfined_uにはアクセス制限が掛けられない。
したがって、RHELではRBACは意味をなさない。
SELinuxの機能
セキュリティコンテキストの構造
| 要素 | 識別子の例 | 説明 |
|---|---|---|
| ユーザ識別子 | system_u | SELinuxユーザを表す。 Linuxユーザとは異なる概念 |
| ロール識別子 | object_r | ユーザが遷移可能なドメインを制限する RBAC (ロールベースアクセス制御) で使用する。 |
| タイプ/ドメイン識別子 | lib_t | プロセス (ドメイン)やファイル (タイプ)を識別 Type Enforcementで使用する。 |
| レベル識別子 | s0 | MLS (Multi Level Security) および MCS (Multi Category Security) で使用。 情報の機密性を表す。 |
SELinuxユーザ
| SELinuxユーザ | 説明 | 備考 |
|---|---|---|
| unconfined_u | アクセス制限のないユーザ | RHELでは全てのLinuxユーザがデフォルトでunconfined_uにマッピングされる。 |
| user_u | 制限された一般ユーザ | 限定的な権限のみ持つ。 |
| staff_u | 管理者補助ユーザ | user_uより権限が多いが、完全な管理者権限はない。 |
| sysadm_u | システム管理者ユーザ | システム管理タスクを実行可能。 |
| system_u | システムプロセス用ユーザ | デーモンやシステムサービスで使用する。 |
| guest_u | ゲストユーザ | 最も制限されたユーザ ネットワークアクセスやsudoの使用不可。 |
| xguest_u | X Window System用ゲストユーザ | guest_uより少し権限が多い GUIアプリケーション使用可能。 |
ロール
| ロール | 対象 | 説明 |
|---|---|---|
| object_r | ファイル | 一般的なファイルのロール ファイルにとってロールは実質的な意味を持たない。(常にobject_r) |
| system_r | プロセス | システムプロセスやデーモンのロール /procディレクトリ下のプロセス関連ファイルにも使用する。 |
| user_r | プロセス | 一般ユーザ (user_u) が起動するプロセスのロール |
| staff_r | プロセス | スタッフユーザ (staff_u) が起動するプロセスのロール |
| sysadm_r | プロセス | システム管理者 (sysadm_u) が起動するプロセスのロール 管理タスクを実行可能 |
| unconfined_r | プロセス | 制限のないロール unconfined_uユーザに関連付けられる。 |
ドメイン (プロセス用)
| 分類 | ドメイン | 説明 |
|---|---|---|
| 制限のないドメイン (Unconfined Domain) |
unconfined_t | ログインユーザが起動するプロセスのドメイン SELinuxによるアクセス制限を受けない。 通常のDACによるアクセス制御は有効。 |
| initrc_t | initまたはsystemdで開始されたシステムプロセスのドメイン SELinuxによる制限なし。 | |
| kernel_t | カーネルプロセスのドメイン カーネルスレッドやカーネル内部処理で使用する。 | |
| 制限のあるドメイン (Confined Domain) |
httpd_t | Apache HTTP Server (httpd)プロセスのドメイン Webサーバとして必要な最小限の権限のみ付与。 |
| sshd_t | SSH デーモン (sshd)のドメイン リモートアクセスに必要な権限のみ。 | |
| crond_t | cronデーモンのドメイン スケジュールされたタスク実行に必要な権限のみ。 | |
| mysqld_t | MySQLデータベースサーバーのドメイン データベース操作に必要な権限のみ。 | |
| ftpd_t | FTPサーバー (vsftpd等)のドメイン ファイル転送に必要な権限のみ。 | |
| named_t | DNS サーバー (BIND)のドメイン DNS問い合わせ処理に必要な権限のみ。 | |
| postfix_t | Postfix メールサーバーのドメイン メール配送に必要な権限のみ。 | |
| samba_t | Sambaサーバーのドメイン ファイル共有に必要な権限のみ。 |
※注意
制限のないドメインは、SELinuxによる防御が無効となるため、システムが侵害された場合のセキュリティリスクが高い。
可能な限り制限のあるドメインを使用することが推奨される。
タイプ (ファイル/オブジェクト用)
| タイプ | 分類 | 説明 |
|---|---|---|
| file_t | デフォルト/未設定 | タイプが明示的に割り当てられていないファイル 制限されたドメインからはアクセス不可。 セキュリティ上の問題を示す可能性がある。 |
| default_t | デフォルト/未設定 | 割り当てるべきタイプが設定されていない場合にデフォルトで付与されるタイプ 制限されたドメインからはアクセス不可。 |
| httpd_sys_content_t | Webコンテンツ | Apache HTTP Serverが読み取り可能なWebコンテンツファイル 静的HTMLファイル等に使用する。 |
| httpd_sys_script_exec_t | Webスクリプト | Apache HTTP ServerがCGIスクリプトとして実行可能なファイル |
| httpd_sys_rw_content_t | Webコンテンツ (R/W) | Apache HTTP Serverが読み書き可能なWebコンテンツ アップロードディレクトリ等に使用する。 |
| admin_home_t | 管理者ホーム | 管理者のホームディレクトリ内のファイル 一般ドメインからはアクセス不可。 |
| user_home_t | ユーザホーム | 一般ユーザのホームディレクトリ内のファイル ユーザ自身のドメインからのみアクセス可能。 |
| tmp_t | 一時ファイル | /tmpディレクトリ内の一般的な一時ファイル |
| var_log_t | ログファイル | /var/logディレクトリ内のログファイル 特定のドメインのみ書き込み可能。 |
| etc_t | 設定ファイル | /etcディレクトリ内の一般的な設定ファイル 多くのドメインから読み取り可能。 |
| bin_t | 実行ファイル | /bin、/usr/binディレクトリ内の一般的な実行可能ファイル |
| lib_t | ライブラリ | /lib、/usr/libディレクトリ内の共有ライブラリファイル |
| device_t | デバイスファイル | /devディレクトリ内のデバイスファイル |
| sysfs_t | sysfs | /sysディレクトリ内のファイル カーネルパラメータやデバイス情報 |
MLSレベル (Multi Level Security)
| レベル | 形式 | 説明 | 使用例 |
|---|---|---|---|
| 単一レベル | s0 | 最低機密性レベル (Unclassified相当) | 一般的なシステムオブジェクト |
| 単一レベル | s1, s2, ... s15 | より高い機密性レベル | 機密情報 s1 : Confidential s2 : Secret s3 : Top Secret相当 |
| 範囲指定 | s0〜s15 | レベル範囲 (s0〜s15まで) | プロセスがアクセス可能なレベル範囲 |
| カテゴリ付き | s0:c0.c1023 | レベル + カテゴリ (MCS) | プロジェクトやテナントの分離 |
| 範囲+カテゴリ | s0〜s15:c0.c1023 | 完全なMLS / MCS形式 | 最も詳細な分類 |
※注意
標準的なSELinuxポリシー (targeted policy) ではMLSは有効化されておらず、全てs0となる。
MLSを使用する場合は、mls policyを使用する必要がある。
各ソフトウェアのポリシー設定
SELinuxを有効にしている場合、サービスが起動しない問題は、SELinuxポリシーによる制限が原因となる場合がある。
SELinuxはセキュリティ上の観点から、プログラムが実行できるアクションを制限することがある。
まず、ポリシーファイルを作成するために必要なライブラリをインストールする。
# RHEL
sudo dnf install checkpolicy policycoreutils-python
# SUSE
sudo zypper install checkpolicy python3-policycoreutils policycoreutils-devel
selinux-tools selinux-policy-devel # その他SELinux関連のツールもインストールする場合
SELinuxのログを確認する。
SELinuxがサービスをブロックしている場合、SELinuxのログにその旨のエラーメッセージが表示される。
まず、SELinuxログを確認する。
sudo tail -f /var/log/audit/audit.log
次に、ポリシーモジュール(TEファイル : Type Enforcement)とポリシーパッケージファイル (PPファイル : Policy Package) ファイルを作成する。
TEファイルとは、特定のドメインに対する全てのタイプとルールを定義するものである。
sudo grep <サービス名> /var/log/audit/audit.log | audit2allow -M <任意のポリシーファイル名>
必要であれば、TEファイルをコンパイルして、ポリシーモジュールファイル(.mod拡張子)を生成する。
checkmodule -M -m -o <任意のポリシーモジュール名>.mod <任意のポリシーモジュール名>.te
または、TEファイルから直接ポリシーパッケージファイル(.pp拡張子)を生成することもできる。
make -f /usr/share/selinux/devel/Makefile
もし、上記でTEファイルからポリシーモジュールファイル(.mod拡張子)を生成した場合、ポリシーパッケージ(.pp拡張子)を生成する。
semodule_package -o <任意のポリシーパッケージ名>.pp -m <任意のポリシーモジュール名>.mod
作成したポリシーモジュールをSELinuxにロードして、ポリシーを有効にする。
sudo semodule -i <任意のポリシーパッケージ名>.pp
ポリシーモジュールの有効化 / 無効化 / 削除
追加したポリシーは、有効化 / 無効化 / 削除することができる。
# ポリシーの有効化 sudo semodule -e <任意のポリシー名> # ポリシーの無効化 sudo semodule -d <任意のポリシー名> # ポリシーの削除 sudo semodule -r <任意のポリシー名>
ポリシーモジュールファイル (TEファイル)
ポリシーモジュールファイル (TEファイル) を作成することにより、特定のソフトウェアやサービスに対するカスタムポリシーを作成できる。
以下に示す要素を組み合わせて、特定のアプリケーションやサービスに対するSELinuxポリシーモジュールを作成することができる。
モジュール宣言
ポリシーパッケージの名前とバージョンを定義する。
これは、TEファイルの最初に記述する必要がある。
policy_moduleマクロを使用すると、自動的にrequire文が追加され、system_rロール、全てのカーネルクラスとパーミッション・オプションでMLS / MCS情報 (sensitivityおよびcategoryステートメント) が含まれる。
- モジュール名
- ポリシーパッケージの名前
- モジュールレイヤー内で一意である必要がある
- バージョン
- ポリシーの更新管理に使用される
- M.m.m形式 (Mはメジャーバージョン、mはマイナーバージョン)
policy_module(<モジュール名>, <バージョン>) # または module <モジュール名> <バージョン>; 例: policy_module(myapp, 1.0.0)
タイプ定義
セキュリティコンテキストの一部となるタイプを定義する。
- タイプ
- SELinuxのセキュリティコンテキストの一部である。
- 一般的に、プロセス用のタイプ (_t)、実行ファイル用のタイプ (_exec_t)、データ用のタイプ (_data_t) 等を定義する。
- タイプ名は、アンダースコアで区切られた意味のある名前にすること。
- タイプ識別子は、全て _t で終わることが慣例である。(強制ではない)
- エイリアス
- オプションでエイリアスを定義できる。
- 複数のエイリアスはスペース区切りで中括弧で囲む。
- 属性
- オプションで事前に宣言された属性を関連付けできる。
- 複数の属性はカンマ区切りで指定する。
type <タイプ名>; type <タイプ名> alias <エイリアス名>; type <タイプ名>, <属性名>; type <タイプ名> alias <エイリアス名>, <属性名>; 例: type myapp_t; type myapp_exec_t; type myapp_data_t; type myapp_log_t alias myapp_log_file_t; type httpd_t, domain, daemon;
属性定義
複数のタイプをグループ化するための属性を定義する。
- 属性名
- 複数のタイプをグループ化するために使用される
- これにより、複数のタイプに対して1度にルールを適用できる
- 例えば、全てのネットワークデーモンに共通のルールを適用する場合等に便利である
- 属性識別子は、タイプと同じ名前空間を共有する
- 慣例として、属性は _t 以外で終わることでタイプと区別される
attribute <属性名>; 例: attribute domain; attribute daemon; attribute file_type;
タイプ属性の割り当て
事前に宣言されたタイプを、事前に宣言された属性に関連付ける。
typeattribute <タイプ名> <属性名> [, <属性名>]; 例: attribute domain; attribute daemon; type myapp_t; typeattribute myapp_t domain, daemon;
ドメイン遷移ルール
プロセスのドメイン変更を定義する。
type_transitionルール
このルールにより、特定のタイプの実行ファイルが実行された時に、プロセスのドメインが自動的に変更される。
以下の例では、unconfined_tドメインのプロセスがmyapp_exec_tタイプの実行ファイルを実行する時、新しいプロセスはmyapp_tドメインで動作する。
type_transition <ソースタイプ> <ターゲットタイプ>:<クラス> <デフォルトタイプ>; # ファイル名遷移 (ポリシーバージョン25以降) type_transition <ソースタイプ> <ターゲットタイプ>:<クラス> <デフォルトタイプ> <オブジェクト名>; 例: type_transition unconfined_t myapp_exec_t:process myapp_t; # ファイル名遷移の例 type_transition unconfined_t etc_t:file system_conf_t eric;
type_transitionルールは、以下に示す3つのallowルールとともに使用される必要がある。
- ソースドメインがターゲットタイプに対してtransitionパーミッションを持つ。
- ソースドメインが実行ファイルタイプに対してread、execute、getattr等のパーミッションを持つ。
- デフォルトドメインが実行ファイルタイプに対してentrypointパーミッションを持つ。
※注意
Reference Policyでは、domain_auto_transマクロがこれらのルールを自動的に生成する。
type_changeルール
ユーザ空間のSELinux対応アプリケーションがオブジェクトのラベルを変更する時に使用される。
これらのアプリケーションは、security_compute_relabel(3) と ポリシー内のtype_changeルールを使用して、適用すべき新しいコンテキストを決定する。
type_change <ソースタイプ> <ターゲットタイプ>:<クラス> <変更後タイプ>; 例: type_change auditadm_t sysadm_devpts_t:chr_file auditadm_devpts_t; type_change staff_t server_ptynode:chr_file staff_devpts_t;
type_memberルール
SELinux対応アプリケーションがオブジェクトの新しいポリインスタンス化されたラベルを定義する時に使用される。
これらのアプリケーションは、avc_compute_member(3) または security_compute_member(3)とポリシー内のtype_memberルールを使用して、適用すべきコンテキストを決定する。
type_member <ソースタイプ> <ターゲットタイプ>:<クラス> <メンバータイプ>; 例: type_member sysadm_t user_home_dir_t:dir user_home_dir_t;
allowルール
基本的なアクセス制御を定義する。
ソースタイプ (通常はプロセス) がターゲットタイプ (ファイルやディレクトリ等) に対して特定の操作を行うことを許可する。
- クラス
- ファイル、ディレクトリ、ソケット等のリソースタイプを指定する。
- パーミッション
- read、write、execute等の操作を指定する。
- ワイルドカード演算子 (*) は、そのオブジェクトクラスのすべてのパーミッションを指定する。
- 補完演算子 (~) は、明示的にリストされたパーミッション以外のすべてのパーミッションを指定する。
- self キーワード
- ターゲットタイプにselfを指定すると、ソースタイプと同じタイプを意味する。
allow <ソースタイプ> <ターゲットタイプ>:<クラス> { <パーミッション> };
例:
allow myapp_t myapp_data_t:file { read write getattr };
allow kernel_t filesystem_type:filesystem mount;
allow staff_t self:capability { setgid chown fowner };
# ワイルドカード演算子の例
allow bootloader_t system_dbusd_t:dbus *;
# 補完演算子の例
allow files_unconfined_type file_type:{ file chr_file } ~execmod;
auditallowルール
イベントを監査記録として記録する。
監査目的で有用な場合に使用する。
このルールはイベントを監査するのみであり、アクセスを許可するにはallowルールが依然として必要である。
auditallow <ソースタイプ> <ターゲットタイプ>:<クラス> { <パーミッション> };
例:
auditallow ada_t self:process execstack;
dontauditルール
拒否メッセージの監査を停止する。
このイベントが常に発生することが既知であり、実際の問題を引き起こさない場合に使用する。
これにより、既知のイベントを除外することで監査ログの管理を支援する。
dontaudit <ソースタイプ> <ターゲットタイプ>:<クラス> { <パーミッション> };
例:
dontaudit traceroute_t { port_type -port_t }:tcp_socket name_bind;
neverallowルール
allowルールが操作に対して生成されてはならないことを指定する。
これは以前に許可されていた場合でも同様である。
neverallow文は、コンパイラで強制されるアクションであり、checkpolicyまたはcheckmoduleコンパイラは、ポリシーソース内にallowルールが生成されているかを確認して、生成されている場合は警告を発して停止する。
neverallow <ソースタイプ> <ターゲットタイプ>:<クラス> { <パーミッション> };
例:
neverallow ~can_read_shadow_passwords shadow_t:file read;
neverallow { domain -mmap_low_domain_type } self:memprotect mmap_zero;
※注意
neverallowステートメントはモジュール内で許可されているが、これらを検出するにはsemanage.confファイルにexpand-check=1エントリが存在する必要がある。
require文
モジュールポリシーソースファイル内で、外部ソースファイルから必要なポリシーコンポーネントを示すために使用される。
require {
<要求リスト>
};
例:
require {
role system_r;
type httpd_t, httpd_exec_t;
class file { read write };
};
| キーワード | 書式 | 説明 | 例 |
|---|---|---|---|
| 識別子リスト型 | role | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { role system_r, user_r; }; |
| type | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { type httpd_t, httpd_exec_t; }; | |
| attribute | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { attribute domain, daemon; }; | |
| user | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { user user_u, staff_u; }; | |
| bool | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { bool httpd_enable_cgi; }; | |
| sensitivity | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { sensitivity s0, s1; }; | |
| category | カンマ区切りの識別子リスト 最後はセミコロンで終わる。 |
require { category c0, c1; }; | |
| class | 単一のクラス識別子 + パーミッションリスト | クラスキーワードの後に、単一のオブジェクトクラス識別子が続き、 その後に1つ以上のパーミッションが続く。 複数のパーミッションは中括弧で囲まれたスペース区切りのリスト |
require { class file { read write }; }; |
複数のキーワードを同一のrequireブロック内で使用することができる。
require {
role system_r;
type httpd_t, httpd_exec_t;
class file { read write getattr };
class dir { search };
};
※注意
requireステートメントキーワードのみが、require {...} ブロック内で許可される。
gen_requireマクロ
Reference Policyマクロとして、モジュールファイル内でrequireブロックを挿入するために使用される。
gen_require(`
<要求ステートメント>
')
例:
gen_require(`
type ftpd_etc_t;
')
インタフェース使用
再利用可能なポリシールールを活用する。
インタフェースは、再利用可能なポリシールールの集合である。
共通の操作 (例: 設定ファイルの読み取り、ログの書き込み) に対して定義されている。
これにより、ポリシーの記述が簡潔になり、一貫性が保たれる。
インタフェース名(<引数1>, <引数2>, ...) 例: files_read_etc_files(myapp_t) logging_log_file(myapp_log_t) domain_type(myapp_t) domain_entry_file(myapp_t, myapp_exec_t)
| インタフェース名 | カテゴリ | 説明 | 引数 | 使用例 |
|---|---|---|---|---|
| files_read_etc_files() | ファイルアクセス | /etcディレクトリ内のファイルの読み取りを許可 | ドメインタイプ | files_read_etc_files(myapp_t) |
| files_type() | タイプ宣言 | ファイルシステムタイプとして宣言する。 ファイルシステム関連の共通属性を自動的に割り当てる。 |
タイプ識別子 | files_type(myapp_data_t) |
| logging_log_file() | タイプ宣言 | ログファイルタイプとして宣言する。 ログディレクトリへのアクセス権限を設定 |
タイプ識別子 | logging_log_file(myapp_log_t) |
| domain_type() | タイプ宣言 | ドメインタイプとして宣言する。 プロセスドメインとしての属性を付与する。 |
タイプ識別子 | domain_type(myapp_t) |
| domain_entry_file() | ドメイン遷移 | ドメインエントリポイントとして宣言する。 指定した実行ファイルからドメインへの遷移を設定 |
ドメインタイプ、実行ファイルタイプ | domain_entry_file(myapp_t, myapp_exec_t) |
| corecmd_exec_bin() | コマンド実行 | /bin、/usr/bin内のコマンドの実行を許可 | ドメインタイプ | corecmd_exec_bin(myapp_t) |
| files_search_etc() | ファイルアクセス | /etcディレクトリの検索を許可 | ドメインタイプ | files_search_etc(myapp_t) |
| files_read_usr_files() | ファイルアクセス | /usrディレクトリ内のファイルの読み取りを許可 | ドメインタイプ | files_read_usr_files(myapp_t) |
| kernel_read_system_state() | システムアクセス | カーネルシステム状態の読み取りを許可 | ドメインタイプ | kernel_read_system_state(myapp_t) |
| corenet_tcp_bind_generic_node() | ネットワーク | 任意のネットワークノードへのTCPバインドを許可 | ドメインタイプ | corenet_tcp_bind_generic_node(myapp_t) |
| logging_search_logs() | ファイルアクセス | ログディレクトリの検索を許可 | ドメインタイプ | logging_search_logs(myapp_t) |
| init_daemon_domain() | タイプ宣言 | initデーモンドメインとして宣言する。 systemdから起動されるサービス用 |
ドメインタイプ、実行ファイルタイプ | init_daemon_domain(myservice_t, myservice_exec_t) |
※注意
これらはReference Policyマクロであり、.ifファイル内で定義されたインタフェースである。
使用時には、各インタフェースのドキュメントを参照して、必要な引数と動作を確認すること。
ブール値の定義
ランタイムでのポリシー調整を可能にする。
ブール値は、ランタイムでポリシーの動作を変更するために使用される。
管理者は、setseboolコマンドを使用してこれらの値を変更できる。
これにより、システムの再起動やポリシーの再コンパイル無しでポリシーを調整できる。
bool <ブール名> <デフォルト値>; 例: bool myapp_enable_feature false; bool allow_execheap false; bool allow_execstack true;
デフォルト値は、true または false である。
条件付きポリシー
動的なポリシー適用を実現する。
条件付きポリシーは、ブール値の状態に基づいてポリシールールを動的に適用または除外する。
これにより、単一のポリシーモジュール内で異なる設定をサポートすることができる。
if (<条件式>) {
<trueリスト>
}
if (<条件式>) {
<trueリスト>
}
else {
<falseリスト>
}
例:
if (myapp_enable_feature) {
allow myapp_t user_home_t:file { read write };
}
if (allow_daemons_use_tty) {
term_use_all_terms(daemon)
}
else {
term_dontaudit_use_all_terms(daemon)
}
条件式で使用可能な論理演算子:
- && (論理AND)
- || (論理OR)
- ^ (排他的OR、XOR)
- ! (論理NOT)
- == (等しい)
- != (等しくない)
if/else構成内で許可されるステートメントとルール:
- allow、auditallow、dontaudit
- type_member、type_change
- type_transition (ファイル名遷移を除く)
- require
※注意
neverallowとauditdeny (非推奨) は条件付きステートメント内では許可されない。
optional文
ポリシーステートメントが最終的にコンパイルされたポリシーに存在する場合と存在しない場合を示すために使用される。
optional {...} 内の全てのステートメントが正常に展開できる場合にのみ、ステートメントがポリシーに含まれる。
これは通常、リストの先頭でrequireステートメントを使用することで実現される。
optional {
<ルールリスト>
}
optional {
<ルールリスト>
} else {
<代替ルールリスト>
}
例:
optional_policy(`
unconfined_domain(ada_t)
')
ロールの割り当て
ユーザのアクセス可能なドメインを制限する。
- ロール
- ユーザがアクセスできるドメイン (タイプ) を制限するために使用される。
- 特定のロールにタイプを関連付けることにより、そのロールを持つユーザのみがそのタイプのプロセスを実行できる。
- ロール識別子は、慣例として _r で終わる。(強制ではない)
role <ロール名> types <タイプ名>; 例: role system_r types myapp_t; role user_r types user_t;
role allowルール
ロールの変更が許可されているかどうかを確認する。
許可されている場合、role_transitionのさらなる要求が行われ、プロセスが新しいロールまたはロールセットで実行される。
allow <ソースロール名> <ターゲットロール名>; 例: allow sysadm_r secadm_r;
role_transitionルール
ロール遷移が必要であることを指定する。
許可されている場合、プロセスは新しいロールで実行される。
ポリシーバージョン25以降、クラスを定義できる。
role_transition <ソースロール> <ターゲットタイプ> <クラス> <デフォルトロール>; 例: role_transition system_r httpd_exec_t:process system_r;
ファイルコンテキストの指定
ファイルシステムのラベリングルールを定義する。
これは、指定されたタイプをファイルタイプとして宣言する。
ファイルタイプには、ファイルシステム関連の共通属性が自動的に割り当てられる。
これにより、ファイルシステムのラベリングルールを簡単に定義できる。
files_type(<タイプ名>) 例: files_type(myapp_data_t) files_type(myapp_log_t)
※注意
files_type()は、Reference Policyマクロであり、ポリシー言語の標準ステートメントではない。
予約語
下表のキーワードは、SELinuxポリシー言語で予約されている。
| 予約語リスト | |||
|---|---|---|---|
| alias | allow | and | attribute |
| attribute_role | auditallow | auditdeny | bool |
| category | cfalse | class | clone |
| common | constrain | ctrue | dom |
| domby | dominance | dontaudit | else |
| equals | false | filename | filesystem |
| fscon | fs_use_task | fs_use_trans | fs_use_xattr |
| genfscon | h1 | h2 | identifier |
| if | incomp | inherits | iomemcon |
| ioportcon | ipv4_addr | ipv6_addr | l1 |
| l2 | level | mlsconstrain | mlsvalidatetrans |
| module | netifcon | neverallow | nodecon |
| not | notequal | number | object_r |
| optional | or | path | pcidevicecon |
| permissive | pirqcon | policycap | portcon |
| r1 | r2 | r3 | range |
| range_transition | require | role | roleattribute |
| roles | role_transition | sameuser | sensitivity |
| sid | source | t1 | t2 |
| t3 | target | true | type |
| typealias | typeattribute | typebounds | type_change |
| type_member | types | type_transition | u1 |
| u2 | u3 | user | validatetrans |
| version_identifier | xor | default_user | default_role |
| default_type | default_range | low | high |
| low_high | |||
ポリシーファイルタイプ別の有効なステートメント
下表に、各タイプのポリシーソースファイルで許可されるステートメントとルールを示す。
| ステートメント/ルール | モノリシックポリシー | ベースポリシー | モジュールポリシー | 条件付きステートメント | optional文 | require文 |
|---|---|---|---|---|---|---|
| allow | 可 | 可 | 可 | 可 | 可 | 不可 |
| allow - Role | 可 | 可 | 可 | 不可 | 可 | 不可 |
| attribute | 可 | 可 | 可 | 不可 | 可 | 可 |
| auditallow | 可 | 可 | 可 | 可 | 可 | 不可 |
| bool | 可 | 可 | 可 | 不可 | 可 | 可 |
| dontaudit | 可 | 可 | 可 | 可 | 可 | 不可 |
| if | 可 | 可 | 可 | 不可 | 可 | 不可 |
| neverallow | 可 | 可 | 可 | 不可 | 可 | 不可 |
| optional | 不可 | 可 | 可 | 可 | 可 | 可 |
| require | 不可 | 可 | 可 | 可 | 可 | 不可 |
| role | 可 | 可 | 可 | 不可 | 可 | 可 |
| role_transition | 可 | 可 | 可 | 不可 | 可 | 不可 |
| type | 可 | 可 | 可 | 不可 | 不可 | 可 |
| type_change | 可 | 可 | 可 | 可 | 可 | 不可 |
| type_member | 可 | 可 | 可 | 可 | 可 | 不可 |
| type_transition | 可 | 可 | 可 | 可 (注1) | 可 | 不可 |
| typeattribute | 可 | 可 | 可 | 不可 | 可 | 不可 |
| user | 可 | 可 | 可 | 不可 | 可 | 可 |
※注意
ファイル名遷移ルールを除く。
一般的なルール
識別子の命名規則
- 識別子は一般的に任意の長さにできるが、以下の文字に制限する必要がある。
- a-z、A-Z、0-9、_ (アンダースコア)
- 慣例により、タイプ識別子は _t で終わる。
- 慣例により、ロール識別子は _r で終わる。
- 慣例により、ユーザ識別子は _u で終わる。
- 属性識別子は、タイプと区別するために _t 以外で終わる。
コメント
- # はポリシーソースファイルでのコメントの開始を示す。
マクロとスペース
- マクロ名とそのパラメータの間にスペースは許可されない。
- 正しい例
- policy_module(ftp, 1.7.0)
- 誤った例
- policy_module (ftp, 1.7.0)
複数エントリの展開
単一のステートメントまたはルールに複数のソースとターゲットエントリが表示される場合、コンパイラ (checkpolicy または checkmodule) はこれらを個別のステートメントまたはルールに展開する。
例:
allow apm_t { console_device_t tty_device_t }:chr_file { getattr read write };
# コンパイラは以下のように展開する:
allow apm_t console_device_t:chr_file { getattr read write };
allow apm_t tty_device_t:chr_file { getattr read write };
設定例
以下に示すようなアプリケーションがあるとする。
- ホームディレクトリ内のファイルを作成、編集、削除
- D-BusおよびPolkitを使用して、/etcディレクトリ内のファイルを作成、編集、削除
- TCP/IP通信を使用して外部ネットワークに接続し、ファイルをダウンロード・アップロード
このアプリケーションのTEファイルでは、以下に示す設定を行う必要がある。
- ホームディレクトリアクセス
- <アプリケーション名>_home_tタイプでホームディレクトリ内のファイル管理を許可する。
- D-Bus / Polkit統合
- システムバスへの接続とPolkit認証を通じた権限昇格をサポート
- ネットワークアクセス
- TCP/IPによる外部接続、HTTP/HTTPS通信、DNS解決を許可
- セキュリティ分離
- 各リソース(ホーム、/etc、一時ファイル、ログ) に個別のタイプを定義して適切に分離
- ブール値によるカスタマイズ
- 管理者が動作を調整できるようにチューナブルブール値を提供する。
- オプショナルポリシー
- 利用可能な場合のみ適用される追加機能 (X11、GNOME等)
policy_module(<アプリケーション名>, 1.0.0)
### 宣言
# プロセスドメインと実行ファイルタイプ
type <アプリケーション名>_t;
type <アプリケーション名>_exec_t;
domain_type(<アプリケーション名>_t)
domain_entry_file(<アプリケーション名>_t, <アプリケーション名>_exec_t)
# ホームディレクトリ内のアプリケーションデータ
type <アプリケーション名>_home_t;
userdom_user_home_content(<アプリケーション名>_home_t)
# 一時ファイル用タイプ
type <アプリケーション名>_tmp_t;
files_tmp_file(<アプリケーション名>_tmp_t)
# /etcディレクトリ内の設定ファイル用タイプ
type <アプリケーション名>_etc_t;
files_config_file(<アプリケーション名>_etc_t)
# ダウンロード/アップロード用の一時保存領域
type <アプリケーション名>_var_lib_t;
files_type(<アプリケーション名>_var_lib_t)
# ログファイル用タイプ
type <アプリケーション名>_log_t;
logging_log_file(<アプリケーション名>_log_t)
### <アプリケーション名> ローカルポリシー
# 基本的なプロセス権限
allow <アプリケーション名>_t self:process { signal_perms getsched setsched };
allow <アプリケーション名>_t self:fifo_file rw_fifo_file_perms;
allow <アプリケーション名>_t self:unix_stream_socket create_stream_socket_perms;
### ホームディレクトリへのアクセス (一般ユーザ権限)
# ホームディレクトリの検索と読み取り
userdom_search_user_home_dirs(<アプリケーション名>_t)
userdom_list_user_home_dirs(<アプリケーション名>_t)
# アプリケーションデータディレクトリの管理
allow <アプリケーション名>_t <アプリケーション名>_home_t:dir manage_dir_perms;
allow <アプリケーション名>_t <アプリケーション名>_home_t:file manage_file_perms;
allow <アプリケーション名>_t <アプリケーション名>_home_t:lnk_file manage_lnk_file_perms;
# ホームディレクトリからの遷移
userdom_user_home_dir_filetrans(<アプリケーション名>_t, <アプリケーション名>_home_t, dir, ".<アプリケーション名>")
userdom_user_home_dir_filetrans(<アプリケーション名>_t, <アプリケーション名>_home_t, file, ".<アプリケーション名>rc")
# 一般的なユーザファイルへの読み取りアクセス (必要に応じて)
userdom_read_user_home_content_files(<アプリケーション名>_t)
userdom_write_user_tmp_files(<アプリケーション名>_t)
### /etcディレクトリへのアクセス (D-Bus / Polkit経由)
# D-Busへの接続
dbus_system_bus_client(<アプリケーション名>_t)
dbus_connect_system_bus(<アプリケーション名>_t)
# Polkitとの通信
optional_policy(`
polkit_dbus_chat(<アプリケーション名>_t)
polkit_domtrans_auth(<アプリケーション名>_t)
')
# /etcディレクトリ内のファイル管理
# 注意 : 実際にはPolkit経由で権限昇格されたプロセスが操作を行うため、直接的なアクセス権限は最小限に抑える
files_search_etc(<アプリケーション名>_t)
allow <アプリケーション名>_t <アプリケーション名>_etc_t:dir manage_dir_perms;
allow <アプリケーション名>_t <アプリケーション名>_etc_t:file manage_file_perms;
# /etc内での新規ファイル作成時の遷移
files_etc_filetrans(<アプリケーション名>_t, <アプリケーション名>_etc_t, file)
files_etc_filetrans(<アプリケーション名>_t, <アプリケーション名>_etc_t, dir)
# Polkit認証のための必要な権限
auth_use_nsswitch(<アプリケーション名>_t)
auth_read_passwd(<アプリケーション名>_t)
# sudo/pkexec経由での実行をサポート
optional_policy(`
sudo_role_template(<アプリケーション名>, <アプリケーション名>_r, <アプリケーション名>_t)
')
### ネットワークアクセス (TCP/IP)
# 基本的なネットワークソケット権限
allow <アプリケーション名>_t self:tcp_socket create_stream_socket_perms;
allow <アプリケーション名>_t self:udp_socket create_socket_perms;
# ネットワークへの接続
corenet_tcp_sendrecv_generic_if(<アプリケーション名>_t)
corenet_tcp_sendrecv_generic_node(<アプリケーション名>_t)
corenet_tcp_connect_all_ports(<アプリケーション名>_t)
corenet_tcp_bind_generic_node(<アプリケーション名>_t)
# HTTP / HTTPS通信 (ダウンロード/アップロード)
corenet_tcp_connect_http_port(<アプリケーション名>_t)
corenet_tcp_connect_http_cache_port(<アプリケーション名>_t)
# DNS解決
sysnet_dns_name_resolve(<アプリケーション名>_t)
# SSLライブラリへのアクセス
miscfiles_read_generic_certs(<アプリケーション名>_t)
miscfiles_read_localization(<アプリケーション名>_t)
### 一時ファイルの管理
# /tmpディレクトリ内の一時ファイル
files_tmp_filetrans(<アプリケーション名>_t, <アプリケーション名>_tmp_t, { file dir })
allow <アプリケーション名>_t <アプリケーション名>_tmp_t:dir manage_dir_perms;
allow <アプリケーション名>_t <アプリケーション名>_tmp_t:file manage_file_perms;
# /var/lib内のデータ保存領域
files_search_var_lib(<アプリケーション名>_t)
allow <アプリケーション名>_t <アプリケーション名>_var_lib_t:dir manage_dir_perms;
allow <アプリケーション名>_t <アプリケーション名>_var_lib_t:file manage_file_perms;
### ログ記録
# ログファイルへの書き込み
logging_search_logs(<アプリケーション名>_t)
allow <アプリケーション名>_t <アプリケーション名>_log_t:dir { add_name write search };
allow <アプリケーション名>_t <アプリケーション名>_log_t:file { create write append setattr };
# システムログへの記録
logging_send_syslog_msg(<アプリケーション名>_t)
### 共通システムリソースへのアクセス
# カーネル情報の読み取り
kernel_read_system_state(<アプリケーション名>_t)
kernel_read_network_state(<アプリケーション名>_t)
# /procファイルシステムの読み取り
dev_read_urand(<アプリケーション名>_t)
dev_read_rand(<アプリケーション名>_t)
# 基本的なコマンドの実行
corecmd_exec_bin(<アプリケーション名>_t)
corecmd_exec_shell(<アプリケーション名>_t)
# 共有ライブラリの読み取り
libs_use_ld_so(<アプリケーション名>_t)
libs_use_shared_libs(<アプリケーション名>_t)
# ローカライゼーションファイルの読み取り
miscfiles_read_localization(<アプリケーション名>_t)
# /usr内のファイルの読み取り
files_read_usr_files(<アプリケーション名>_t)
### デスクトップ環境との統合 (DEの使用時)
optional_policy(`
# X11との通信
xserver_user_x_domain_template(<アプリケーション名>, <アプリケーション名>_t, <アプリケーション名>_tmpfs_t)
')
optional_policy(`
# GNOMEキーリングへのアクセス
gnome_stream_connect_gkeyringd(<アプリケーション名>_t)
')
### ブール値によるオプション機能
## <desc>
## <p>
## <アプリケーション名>が全てのユーザファイルへの読み書きを許可する
## </p>
## </desc>
gen_tunable(<アプリケーション名>_manage_all_user_content, false)
if (<アプリケーション名>_manage_all_user_content) {
userdom_manage_user_home_content_files(<アプリケーション名>_t)
userdom_manage_user_home_content_dirs(<アプリケーション名>_t)
}
## <desc>
## <p>
## <アプリケーション名>がroot権限でのファイル操作を実行することを許可する
## </p>
## </desc>
gen_tunable(<アプリケーション名>_allow_privileged_operations, true)
if (<アプリケーション名>_allow_privileged_operations) {
# Polkit経由での権限昇格を許可
optional_policy(`
polkit_domtrans_auth(<アプリケーション名>_t)
')
}
### オプション : ユーザドメインからの起動を許可
optional_policy(`
# unconfined_tドメインからの起動
unconfined_domain(<アプリケーション名>_t)
')
# 一般ユーザドメインからのドメイン遷移
userdom_use_user_terminals(<アプリケーション名>_t)
# ユーザプロセスからの起動を許可
allow unconfined_t <アプリケーション名>_exec_t:file { execute execute_no_trans };
domtrans_pattern(unconfined_t, <アプリケーション名>_exec_t, <アプリケーション名>_t)
### セキュリティ強化オプション
# メモリ実行保護 (必要な場合のみコメント解除)
# allow <アプリケーション名>_t self:process { execmem execstack };
# ファイルディスクリプタの継承制限
dontaudit <アプリケーション名>_t domain:process { noatsecure siginh rlimitinh };
# 監査を無効化する一般的な拒否
dontaudit <アプリケーション名>_t self:capability { sys_resource sys_nice };