Translated message

A translation of this page exists in English.

カスタム SELinux ポリシーを作成するためのクイックスタート

更新 -

Table of Contents

システム上で SELinux によって制限された新しいアプリケーションを実行するには、ディストリビューション SELinux ポリシーによって適用されるルールを補足するカスタムポリシーファイルを準備します。

ポリシーテンプレートの生成

policycoreutils-devel パッケージによって提供される sepolicy 生成 ツールは、最初のステップの実行に役立ちます。このツールは、基本ポリシーモジュール、Makefile、およびセットアップスクリプトを生成します。このスクリプトはポリシーモジュールを構築してインストールし、.fc ファイルで定義されたパスのラベルを変更します。このコマンドは通常のユーザーとして使用できます。次に例を示します。

$ sepolicy generate --init <path_to_my_app_binary>

詳細については、RHEL の SELinux の使用に関するドキュメント のカスタムアプリケーションの SELinux ポリシーの作成と強制 セクションを参照してください。

グラフィカルインターフェイスとウィザードを使用したい場合は、policycoreutils-gui パッケージで提供される selinux-polgengui ツールを使用できます。

生成されたポリシーテンプレートには、次のポリシーファイルが含まれています。

  • <mypolicy> .te - アプリケーションで使用されるポリシールールと新しいタイプおよびドメインを定義します。
  • <mypolicy> .fc - ファイルコンテキスト定義、つまりアプリケーションに関連するファイルにラベルを付けるための指示が含まれています
  • <mypolicy> .if - インターフェイスが含まれます。インターフェイスは、このポリシーと対話するために他のポリシーモジュールによって使用されるポリシーマクロです。

アプリケーションの動作に基づいてアクセスを許可する

システムに初期ポリシーをインストールした後、アプリケーションに必要なアクセスに基づいてポリシーを改善できます。

アクセスされたすべてのパスをログに含めるには、完全な監査を有効にします。

# audictl -d never,task
# auditctl -w /etc/ -p w

あるいは、/etc/audit/rules.d/ audit.rules ファイルを開き、-a task,never が存在する場合は削除し、-w/etc/-pw を追加して、Audit デーモンを再起動します。

SELinux ポリシーのすべての違反をログに記録するには、SELinux を 許可 モードに切り替えます。

# setenforce 0

setenforce 0 コマンドは、次回再起動するまで、SELinux をシステム全体で許可モードに設定します。新しいドメインのみを許可モードに切り替え、残りの SELinux ポリシーを強制モードのままにすることができます。

# semanage permissive -a <myapp_t>

sepolicy generated コマンドは、許可的な <myapp_t> ルールをポリシーモジュールに追加することに注意してください。したがって、ルールを保存した場合は、この手順をスキップできます。

完全な監査と許容モードを有効にした後、新しい SELinux ドメインでアプリケーションを実行します。アプリケーションに必要なすべてのアクセスを確認するには、できるだけ多くの使用例をテストします。システムは、現在のポリシーで許可されていないすべてのアクセス要求を AVC (SELinux アクセス拒否ログ) の形式で記録します。

AVC の処理

SELinux がアクションを拒否すると、システムは Access Vector Cache (AVC) メッセージを /var/log/audit/audit.log および /var/log/messages ファイルに追加するか、Journal デーモンが拒否をログに記録します。
ausearch コマンドを使用して、最近の AVC を表示できます。例:

# ausearch -m AVC,USER_AVC -ts recent

-ts Recent パラメーターは検索を 10 分間に制限しますが、代わりにタイムスタンプを使用できます。

Audit2allow ツールは AVC を処理し、ポリシーに対応する 許可 ルールを生成できます。

カスタムルールが他のポリシーパッケージで定義されたリソースと対話する場合は、可能であれば、単純な 許可 ルールの代わりに インターフェイスを 使用してください。Audit2allow -R コマンドは、代わりに、ユースケースをカバーするインターフェイスの検索を試みます。このコマンドの各結果をチェックして、結果として得られるポリシーが緩すぎないことを確認する必要があります。

ポリシーマクロ

ポリシーマクロ (パターンまたはより複雑な場合はインターフェイスとも呼ばれます) は、特定の使用例を許可するために連携して機能する複数のルールを生成します。

以下に例を示します。

  • インターフェイス:
    • mysql_read_config (<domain>) - 指定されたドメイン (この例では httpd_t) に MySQL 設定ファイルへの読み取りアクセスを与えます。
    • init_daemon_domain (<domain>、<file_type>) - 最初の引数として指定されたタイプをドメインにプロモートします。 init デーモンによって実行可能ファイルのエントリーポイントとして使用されます。
  • パターン:
    • rw_files_pattern (< ドメイン >、< ディレクトリータイプ >、< ファイルタイプ >) - を与えるラベルが付いたファイルへの読み取りおよび書き込みアクセスというラベルのディレクトリーにあります
    • domtrans_pattern (<source>、<entrypoint>、<target>) - 自動ドメイン移行を設定します: ドメイン内でプロセスが実行されているときというラベルの付いたバイナリーを実行します、結果のプロセスはドメインで実行されます

Fedora、RHEL、および CentOS で使用できるインターフェイスは、selinux-policy Github リポジトリーの モジュール セクションで定義されています。各ポリシーモジュールには、他のモジュールがモジュール内で定義されたリソースにアクセスするための手段として、一連のインターフェイスが含まれています。

各マクロには、指定する必要がある引数の数が固定されています。対応する引数がわからない場合は、マクロの本体で、$ 文字の後にインデックスが続く形式の引数参照 ($1 など) を確認してください。または、selinux-policy-doc パッケージによって提供される /usr/share/doc/selinux-policy/html/interfaces.html ファイル内のインターフェイスインデックスを確認します。

オプションのポリシー

いずれかの コントリビューションモジュール で定義されたインターフェイスを使用する場合は、それを Optional_policy ブロックで囲む必要があります。

たとえば、Apache モジュールは、kerberos module で定義された kerberos_read_keytab インターフェイスを使用します。

optional_policy(`
kerberos_read_keytab(httpd_t)
')

Optional_policy ブロックにより、オプションモジュールなしでポリシーモジュールを使用できるようになります。この場合、kerberos モジュールが削除されたシステムで Apache モジュールを使用できる可能性があります。Optional_policy ブロックを省略した場合、アクセスを許可したリソースが存在するモジュールが見つからない場合、新しいポリシーモジュールをインストールするとエラーが発生します。

マクロのデプロイメント

selinux-policy-devel パッケージによって提供される マクロデプロイメント ツールは、名前が一目瞭然でない場合、各マクロに含まれる内容を表示します。すべての引数を含む完全なマクロ名を指定して Macro-expander を 使用すると、マクロが生成するすべての許可ルールが表示されます。次に例を示します。

# macro-expander "mysql_read_config(httpd_t)" 
allow httpd_t mysqld_etc_t:dir { getattr search open read lock ioctl };
allow httpd_t mysqld_etc_t:file { open { getattr read ioctl lock } };
allow httpd_t mysqld_etc_t:lnk_file { getattr read };

マクロデプロイメント リストでは、デフォルトではルールのみ が許可されること に注意してください。type_transition ルールや属性の割り当てなど、マクロの完全な内容を表示するには、macro-expander -M <> を使用し、モジュールヘッダーとすべての require ブロックを無視します。

$ macro-expander -M "domtrans_pattern(<source>, <entrypoint>, <target>)"
module expander 1.0.0;
require {
role system_r;
...
}
allow <source> <entrypoint>:file { getattr open map read execute ioctl execute_no_trans };
allow <source> <target>:process transition;
type_transition <source> <entrypoint>:process <target>;
allow <target> <source>:fd use;
allow <target> <source>:fifo_file { getattr read write append ioctl lock };
allow <target> <source>:process sigchld;

権限セット

他のポリシーマクロとは異なり、アクセス許可セットは引数を使用せず、一般的に一緒に使用されるアクセス許可のセットの短縮形としてのみ機能します。

以下に例を示します。

  • rw_file_perms - { getattr を開く読み取り書き込み ioctl ロックを追加 }
  • create_dir_perms - { getattr create }
  • append_fifo_file_perms - { getattr open append lock ioctl }

すべての権限セットは、obj_perm_sets.spt ファイルで定義されます。マクロエキスパンダー ではデフォルトで 許可 ルールのみが表示されるため、スタンドアロン権限セットをデプロイメントするには次のようにコマンドを調整する必要があります。

$ macro-expander -M "manage_blk_file_perms" | tail -n 1
{ create open getattr setattr read write append rename link unlink ioctl lock }

この場合、-M オプションを指定した マクロデプロイメント により、クエリーを含む完全なモジュールが生成され、モジュールヘッダーと require ブロックは無視できます。

あるいは、次のようにダミー許可ルールを指定します。

$ macro-expander "allow _ _:_ manage_blk_file_perms"
allow _ _:_ { create open getattr setattr read write append rename link unlink ioctl lock }

インターフェイスがありません

インターフェイスが存在しない有効なアクセス要件を許可したい場合は、gen_require ステートメントを使用して問題を回避します。

次の例では、dhcpd ポリシーモジュールは、audit2allow -R コマンドの出力にリストされている AVC に基づいて追加のアクセスを必要とします。

$ audit2allow -R
type=AVC msg=audit(1674838508.590:840): avc: denied { write } for pid=2383 comm="dhcpd" name="bluetooth.conf" dev="vda2" ino=2 scontext=system_u:system_r:dhcpd_t:s0 tcontext=system_u:object_r:bluetooth_conf_t:s0 tclass=file permissive=1

require {
type bluetooth_conf_t;
type dhcpd_t;
class file write;
}

#============= dhcpd_t ==============
allow dhcpd_t bluetooth_conf_t:file write;

bluetooth_conf_t ファイルに書き込むためのインターフェイスは存在しませんが、selinux-policy Github リポジトリーの bluetooth.if ファイルを簡単に検索すると、bluetooth_read_config が表示されます。これは、この使用例に合わせて変更できます。

interface(`bluetooth_read_config',`
gen_require(`
type bluetooth_conf_t;
')

allow $1 bluetooth_conf_t:file read_file_perms;
')

read_file_perms をwrite_file_perms 1 に置き換え、インターフェイス引数 ($1 -> dhcpd_t) を入力することで、欠落しているアクセスを修正します。

また 、Bluetooth モジュールで定義された実際のインターフェイスを使用する場合と同様に、追加したポリシーを Optional_policy ブロックで囲む必要があります。

optional_policy(`
gen_require(`
type bluetooth_conf_t;
')

allow dhcpd_t bluetooth_conf_t:file write_file_perms;
')

プロセスコンテキスト (ドメイン)

実行中のプロセスに割り当てられたタイプは、多くの場合、ドメイン と呼ばれます。デフォルトでは、新しいプロセスは親のコンテキストを継承します。たとえば、unconfined_t ドメインで実行されている Bash シェルでユーザーが cat コマンドを入力すると、新しいプロセスが unconfined_t としても実行されます。

この動作は、domtrans_pattern (ドメイン遷移パターン) の一部である type_transition ルールを使用して変更できます。

domtrans_pattern(<source>, <entrypoint>, <target>)

このパターンは、type_transition ルールを使用して <target> ドメインへの自動遷移を定義し、遷移を許可する一連のルールを追加します。これは通常、init_t (init デーモンドメイン) と新しく作成されたドメイン間の移行を容易にするために 、init_daemon_domain (<target>、<entrypoint>) インターフェイスの一部として使用されます。

ファイルコンテキスト

新しいファイルは、ファイルを作成したディレクトリーに割り当てられたタイプを継承します。アプリケーションコードを変更せずにカスタムタイプを割り当てるには、filetrans_pattern マクロを使用します。

filetrans_pattern(<process_domain>, <directory>, <target_type>, <class(es)>, [<name>])

説明:

  • <class (es)> - ルールが適用されるオブジェクトクラス (ファイル、ディレクトリー、ソケットなど)
  • - ルールを指定された 名前 のオブジェクトに制限します (オプション)

以下に例を示します。

filetrans_pattern(httpd_t, var_t, httpd_cache_t, file, "apache_cache")

httpd_t として実行されているプロセスが var_t というラベルの付いたディレクトリーに apache_cache という名前のファイルを作成すると、システムは結果のファイルに httpd_cache_t ラベルを設定します。

より特殊なマクロ内で filetrans_pattern を 使用できます。その場合、<directory> 引数は特定の場所に基づいて事前に入力されます。次に例を示します。

files_var_filetrans(httpd_t, httpd_cache_t, { file dir })

詳細については、RHEL 7 SELinux ユーザーおよび管理者ガイドの ファイル名の移行 セクションを参照してください。

デフォルトのファイルコンテキスト定義

すべてのポリシーモジュールには、リソースのデフォルトの SELinux コンテキストを決定する ファイルコンテキスト定義ファイル<module>.fc が含まれています。このコンテキストは、matchpathconrestorecon などのラベル付けユーティリティーによって使用されます。

各定義の形式は次のとおりです。

pathname_regexp [file_type] security_context

説明:

  • pathname_regexp - 正規表現の形式でパス名を定義します。
  • file_type - オブジェクトクラスを表し、空白 (すべてのオブジェクトクラスを意味する) または次のいずれかです。
    • -b - デバイスをブロックする
    • -c - キャラクターデバイス
    • -d - ディレクトリー
    • -p - 名前付きパイプ (FIFO)
    • -l - シンボリックリンク
    • -s - ソケットファイル
    • -- - 通常のファイル
  • security_context - パスに割り当てられたデフォルトのセキュリティーコンテキスト

詳細については、RHEL 7 SELinux ユーザーおよび管理者ガイドの SELinux コンテキスト – ファイルのラベル付け セクションを参照してください。

CIL エラーのトラブルシューティング

コンパイルされたポリシーモジュールをシステムにロードすると、コンパイラーはモジュールコードを共通中間言語 (CIL) に変換します。これは、システムポリシーにすでに存在するタイプ定義を持つ次の単純なポリシーの例に示されているように、モジュールのロード中に発生したほとんどのエラーがポリシーの CIL バージョンに対して報告されることを意味します。

$ sepolicy generate --init /usr/bin/cat

$ echo "type abrt_t;" >> cat.te

$ sudo make -f /usr/share/selinux/devel/Makefile cat.pp
Compiling targeted cat module
Creating targeted cat.pp policy package
rm tmp/cat.mod.fc tmp/cat.mod

$ sudo semodule -i cat.pp
Re-declaration of type abrt_t
Previous declaration of type at /var/lib/selinux/targeted/tmp/modules/400/cat/cil:6
Bad type declaration at /var/lib/selinux/targeted/tmp/modules/400/cat/cil:6
Failed to build AST
semodule: Failed!

一部の CIL 関連のエラーメッセージは明確ではないため、モジュールソースコードの CIL 変換内の対応する行を確認する必要がある場合があります。この特定のケースでは、エラーは行 6 に関連しています。pp ツールを使用してポリシーバイナリーを CIL に変換し、問題のある行を表示します。

$ cat cat.pp | /usr/libexec/selinux/hll/pp > cat.cil
$ head -6 cat.cil | tail -1
(type abrt_t)

CIL の詳細と、そのキーワードがソースポリシー言語とどのように異なるかについては、SELinux プロジェクト wiki の CIL ポリシー言語 セクションを参照してください。

ポリシーの例

次の手順例を実行すると、bootupd パッケージ用の新しい SELinux ポリシーを作成してテストできます。パッケージには、現在制限されていないサービスが含まれています。

bootupd パッケージによってインストールされたすべてのファイルを表示します。

$ rpm -ql bootupd
/usr/bin/bootupctl
/usr/lib/.build-id
/usr/lib/.build-id/e8
/usr/lib/.build-id/e8/3c00b4a3c33f2858d6730e9ba95d8286ab6dde
/usr/lib/.build-id/e8/3c00b4a3c33f2858d6730e9ba95d8286ab6dde.1
/usr/lib/systemd/system/bootupd.service
/usr/lib/systemd/system/bootupd.socket
/usr/libexec/bootupd
/usr/share/doc/bootupd
/usr/share/doc/bootupd/README.md
/usr/share/licenses/bootupd
/usr/share/licenses/bootupd/LICENSE

リストされたファイルの中には、2 つのユニットファイルと 2 つのバイナリー、bootupd および bootupctl (リモートコマンドラインインターフェイス) が表示されます。新しい SELinux ポリシーの準備では、残りのファイルは無視してかまいません。

bootupd.socket ファイルは、サービスが /var/run/bootupd.sock ソケットを使用することを示します。bootupd サービスのユニットファイルは init システムを使用するため、sepolicygenerate コマンドで --init パラメーターを使用します。bootupd.service ファイルの内容に基づいて、/usr/libexec/bootupd が サービスバイナリーであることがわかります。残りのファイル (ユニットファイルとソケットファイル) を --writepath パラメーターの値として使用して、sepolicy generated コマンドでそれらのファイルがポリシーに含まれるようにします。

$ sepolicy generate --init /usr/libexec/bootupd -w /usr/lib/systemd/system/bootupd.service /usr/lib/systemd/system/bootupd.socket /var/run/bootupd.sock
Created the following files:
/home/user/bootupd/bootupd.te # Type Enforcement file
/home/user/bootupd/bootupd.if # Interface file
/home/user/bootupd/bootupd.fc # File Contexts file
/home/user/bootupd/bootupd_selinux.spec # Spec file
/home/user/bootupd/bootupd.sh # Setup Script

bootupd.te タイプ強制ファイルには、次の 4 つの新しいタイプが含まれています。
* bootupd_t - bootupd プロセスのドメイン
* bootupd_exec_t - bootupd バイナリーのファイルタイプ
* bootupd_var_run_t - /var/run/bootupd.sock ソケットのタイプ
* bootupd_unit_file_t - 2 つのユニットファイルのファイルタイプ

init_daemon_domain (bootupd_t、bootupd_exec_t) マクロは、init デーモンが bootupd バイナリーを実行するときに、結果のプロセスが bootupd_t ドメインで実行されるようにします。

生成されたモジュールの残りの部分は、bootupd_var_run_t へのアクセスを許可するマクロのグループを除き、ほとんどが init デーモンポリシーテンプレートです。
* manage_dirs_pattern (bootupd_t、bootupd_var_run_t、bootupd_var_run_t) - bootupd_var_run_t というラベルの付いたディレクトリーを管理します
* manage_files_pattern (bootupd_t、bootupd_var_run_t、bootupd_var_run_t) - bootupd_var_run_t というラベルの付いたファイルを管理します
* manage_lnk_files_pattern (bootupd_t、bootupd_var_run_t、bootupd_var_run_t) - bootupd_var_run_t というラベルの付いたリンクファイルを管理します
* files_pid_filetrans (bootupd_t、bootupd_var_run_t、{ dir file lnk_file }) - bootupd_t がvar_run_t というラベルの付いたディレクトリーにファイルを作成した場合、結果のファイルには bootupd_var_run_t というラベルが付けられます。

/var/run/bootupd.sock パスが存在しないため、sepolicy generated はディレクトリー、ファイル、およびリンクファイルのアクセスマクロを生成します。/var/run/bootupd.sock は ソケットファイルであるため、3 つの manage_* パターンをすべて削除できます。selinux-policy Github リポジトリーの file_patterns.spt ファイルには、代わりに使用できるいくつかの ソケット パターン (rw_sock_files_pattern など) が含まれています。

ソケットファイルは、systemctl start bootupd.socket を使用した結果として systemd (bootupd ではなく) によって生成されるため、files_pid_filetrans マクロも冗長です。アプリケーションのバイナリーがソケットファイルを生成する場合は、files_pid_filetrans` の行を削除する代わりに、 { dir file lnk_file } を { sock_file } 置き換える必要があります。

bootupd.fc ファイルコンテキスト設定ファイルには、sepolicy generated コマンドに指定されたすべてのパスも含まれています。

/usr/lib/systemd/system/bootupd.service         --      gen_context(system_u:object_r:bootupd_unit_file_t,s0)
/usr/lib/systemd/system/bootupd.socket -- gen_context(system_u:object_r:bootupd_unit_file_t,s0)
/usr/libexec/bootupd -- gen_context(system_u:object_r:bootupd_exec_t,s0)
/var/run/bootupd.sock -- gen_context(system_u:object_r:bootupd_var_run_t,s0)

繰り返しますが、sepolicy generated は ソケットファイルを正しく認識しませんでした。したがって、オブジェクトクラスを -- (通常のファイル) から -s (ソケットファイル) に変更する必要があります。

/var/run/bootupd.sock           -s      gen_context(system_u:object_r:bootupd_var_run_t,s0)

オブジェクトクラスの完全なリストについては 、デフォルトのファイルコンテキスト定義 セクションを参照してください。

この手順の後、新しいポリシーがパッケージと一致します。コンパイルしてインストールします。

$ make -f /usr/share/selinux/devel/Makefile bootupd.pp
Compiling targeted bootupd module
Creating targeted bootupd.pp policy package
rm tmp/bootupd.mod.fc tmp/bootupd.mod

$ sudo semodule -i bootupd.pp

新しいファイルコンテキスト定義の影響を受ける各パスで restorecon コマンドを使用して、システムに設定を適用します。

$ sudo restorecon -v /usr/libexec/bootupd /usr/lib/systemd/system/bootupd.socket /usr/lib/systemd/system/bootupd.service
Relabeled /usr/libexec/bootupd from system_u:object_r:bin_t:s0 to system_u:object_r:bootupd_exec_t:s0
Relabeled /usr/lib/systemd/system/bootupd.socket from system_u:object_r:systemd_unit_file_t:s0 to system_u:object_r:bootupd_unit_file_t:s0
Relabeled /usr/lib/systemd/system/bootupd.service from system_u:object_r:systemd_unit_file_t:s0 to system_u:object_r:bootupd_unit_file_t:s0

完全な監査を 有効にした後、サービスを実行します。

$ sudo systemctl start bootupd.socket

$ sudo systemctl start bootupd

ファイルコンテキストとサービスプロセスのドメインを確認してください。ログで AVC を検索します。

$ ls -lZ /var/run/bootupd.sock
srw-------. 1 root root system_u:object_r:bootupd_var_run_t:s0 0 Mar 14 10:45 /var/run/bootupd.sock

$ ps -axZ | grep bootup[d]
system_u:system_r:bootupd_t:s0 2508 ? Ss 0:00 /usr/libexec/bootupd daemon -v

$ sudo ausearch -m AVC | tee avc.log
----
time->Tue Mar 14 10:24:55 2023
type=PROCTITLE msg=audit(1678803895.889:613): proctitle=2F7573722F6C6962657865632F626F6F74757064006461656D6F6E002D76
type=SYSCALL msg=audit(1678803895.889:613): arch=c000003e syscall=41 success=yes exit=4 a0=1 a1=80002 a2=0 a3=8080808080808080 items=0 ppid=1 pid=1995 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bootupd" exe="/usr/libexec/bootupd" subj=system_u:system_r:bootupd_t:s0 key=(null)
type=AVC msg=audit(1678803895.889:613): avc: denied { create } for pid=1995 comm="bootupd" scontext=system_u:system_r:bootupd_t:s0 tcontext=system_u:system_r:bootupd_t:s0 tclass=unix_dgram_socket permissive=1
----
time->Tue Mar 14 10:24:55 2023
type=PROCTITLE msg=audit(1678803895.889:614): proctitle=2F7573722F6C6962657865632F626F6F74757064006461656D6F6E002D76
type=SYSCALL msg=audit(1678803895.889:614): arch=c000003e syscall=44 success=yes exit=8 a0=4 a1=557718261310 a2=8 a3=4000 items=0 ppid=1 pid=1995 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bootupd" exe="/usr/libexec/bootupd" subj=system_u:system_r:bootupd_t:s0 key=(null)
type=AVC msg=audit(1678803895.889:614): avc: denied { sendto } for pid=1995 comm="bootupd" path="/run/systemd/notify" scontext=system_u:system_r:bootupd_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=unix_dgram_socket permissive=1
----
time->Tue Mar 14 10:24:55 2023
type=PROCTITLE msg=audit(1674838508.590:840): proctitle=2F7573722F6C6962657865632F626F6F74757064006461656D6F6E002D76
type=PATH msg=audit(1674838508.590:840): item=0 name="/boot/efi" inode=413 dev=fc:02 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:boot_t:s0 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(1674838508.590:840): cwd="/usr"
type=SYSCALL msg=audit(1674838508.590:840): arch=c000003e syscall=137 success=yes exit=0 a0=7fff3dc6b6a0 a1=7fff3dc6c7c0 a2=9 a3=fff items=1 ppid=1 pid=2383 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bootupd" exe="/usr/libexec/bootupd" subj=system_u:system_r:bootupd_t:s0 key=(null)
type=AVC msg=audit(1674838508.590:840): avc: denied { getattr } for pid=2383 comm="bootupd" name="/" dev="vda2" ino=2 scontext=system_u:system_r:bootupd_t:s0 tcontext=system_u:object_r:fs_t:s0 tclass=filesystem permissive=1

サービスが新しいドメインで実行されており、ソケットファイルに正しいラベルが付いている場合でも、SELinux は依然としてポリシーで許可されていない 3 つのアクセスベクトルを報告しました。AVC メッセージの詳細な説明については、RHEL 9 の SELinux の使用ドキュメント の監査ログセクションの SELinux 拒否を 参照してください。

新しいポリシーに欠落している許可ルールの 提案を 得るには、audit2allow ツールを使用できます。

$ audit2allow -i avc.log

#============= bootupd_t ==============
allow bootupd_t fs_t:filesystem getattr;
allow bootupd_t kernel_t:unix_dgram_socket sendto;
allow bootupd_t self:unix_dgram_socket create;

別のポリシーモジュール (fs_t および kernel_t) で定義されたタイプを含むポリシーモジュールをコンパイルすることはできないため、必要なルールを含むインターフェイスまたはマクロに対しては、audit2allow を-R オプションとともに使用する必要があります。

$ audit2allow -R -i avc.log

require {
type bootupd_t;
class unix_dgram_socket create;
}

#============= bootupd_t ==============
allow bootupd_t self:unix_dgram_socket create;
fs_getattr_xattr_fs(bootupd_t)
kernel_dgram_send(bootupd_t)

提案されたインターフェイスが、macro-expander を使用して必要なユースケースを正確にカバーしていることを確認した後、それらをポリシーモジュールに追加します。また、コントリビューションモジュール から派生したインターフェイスも、optional_policy ブロックで囲む必要があります。最初に新しいポリシーを寛容モードでデプロイメントし、さまざまなシステム設定でできるだけ多くの使用シナリオをテストします。

その他のリソース


  1. selinux-policy Github リポジトリーの obj_perm_sets.spt にあります ↩︎

Comments