Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

第10章 SELinux systemd のアクセス制御

Red Hat Enterprise Linux 7 では、システムサービスは systemd デーモンにより制御されます。Red Hat Enterprise Linux の以前のリリースでは、デーモンを起動する方法が 2 つありました。
  • システムの起動時に、System V init デーモンはinit.rc スクリプトを起動し、このスクリプトにより必要なデーモンを起動します。たとえば、システムの起動時に起動した Apache サーバーには、以下の SELinux ラベルが貼られています。
    system_u:system_r:httpd_t:s0
  • 管理者が手動でinit.rc スクリプトを起動すると、デーモンが実行します。たとえば、service httpd restart コマンドを Apache サーバーで実行すると、表示される SELinux ラベルは次のようになります。
    unconfined_u:system_r:httpd_t:s0
手動で開始すると、このプロセスでは、開始した SELinux ラベルのユーザー部分が採用され、上記の 2 つのシナリオでのラベリングに矛盾が発生します。systemd デーモンでは、遷移が大きく異なります。systemd は、init_t タイプを使用して、システムでデーモンを開始および停止するすべての呼び出しを処理するため、デーモンを手動で再起動すると、ラベルのユーザー部分を上書きできます。その結果、上記の両方のシナリオのラベルは、期待どおりに system_u:system_r:httpd_t:s0 で、SELinux ポリシーを改善して、どのドメインがどのユニットを制御できるかを管理できます。

10.1. サービスへの SELinux のアクセス権限

以前のバージョンの Red Hat Enterprise Linux では、管理者は System V Init スクリプトのラベルに基づいて、どのユーザーまたはアプリケーションがサービスを開始または停止できるかを制御できました。現在、systemd はすべてのサービスを開始および停止し、ユーザーとプロセスは、systemctl ユーティリティーを使用して systemd と通信します。systemd デーモンは、SELinux ポリシーを調べ、呼び出しているプロセスのラベルと、呼び出し元が管理しようとしているユニットファイルのラベルを確認してから、呼び出し元のアクセスを許可するかどうかを SELinux に確認します。このアプローチにより、システムサービスの開始や停止などの、重要なシステム機能へのアクセス制御が強化されます。
たとえば、管理者は、NetworkManager が systemctl を実行して D-Bus メッセージを systemd に送信できるようにする必要がありました。これにより、NetworkManager が要求するサービスが開始または停止します。実際、NetworkManager は、systemctl ができることをすべて実行できるようになっていました。また、特定のサービスのみを開始または停止できるように、限定管理者を設定することもできませんでした。
この問題を修正するために、systemd は SELinux Access Manager としても機能します。systemctl を実行しているプロセス、またはsystemd に D-Bus メッセージを送信したプロセスのラベルを取得できます。次に、デーモンは、プロセスが設定するユニットファイルのラベルを探します。最後に、SELinux ポリシーでプロセスラベルとユニットファイルラベルとの間で特定のアクセスが許可されている場合、systemd はカーネルから情報を取得できます。これは、特定のサービスに対して、systemd と相互作用を必要とする、危険にさらされたアプリケーションを SELinux が制限できることを意味します。ポリシー作成者は、このような粒度の細かい制御を使用して、管理者を制限することもできます。ポリシーの変更には、以下のパーミッションを持つ service という名前の新しいクラスが関与します。
class service
{
       start
       stop
       status
       reload
       kill
       load
       enable
       disable
}
たとえば、ポリシーの作成者は、ドメインがサービスのステータスを取得したり、サービスを開始および停止したりできるようになりましたが、サービスを有効または無効にすることはできません。SELinux および systemd でのアクセス制御操作は、すべての場合で一致するわけではありません。systemd メソッドの呼び出しを SELinux アクセスチェックと揃えるために、マッピングが定義されています。表10.2「SELinux アクセスチェックでの systemd 一般システムコールのマッピング」 は、システム全般のアクセスチェックをカバーするのに対し、表10.1「SELinux アクセスチェックでの systemd ユニットファイルメソッド呼び出しのマッピング」 は、ユニットファイルのアクセスチェックをマップします。いずれかのテーブルに一致するものが見つからない場合は、undefined システムチェックが呼び出されます。

表10.1 SELinux アクセスチェックでの systemd ユニットファイルメソッド呼び出しのマッピング

systemd ユニットファイルメソッド SELinux アクセスチェック
DisableUnitFiles disable
EnableUnitFiles enable
GetUnit status
GetUnitByPID status
GetUnitFileState status
Kill stop
KillUnit stop
LinkUnitFiles enable
ListUnits status
LoadUnit status
MaskUnitFiles disable
PresetUnitFiles enable
ReenableUnitFiles enable
Reexecute start
Reload reload
ReloadOrRestart start
ReloadOrRestartUnit start
ReloadOrTryRestart start
ReloadOrTryRestartUnit start
ReloadUnit reload
ResetFailed stop
ResetFailedUnit stop
Restart start
RestartUnit start
開始 start
StartUnit start
StartUnitReplace start
停止 stop
StopUnit stop
TryRestart start
TryRestartUnit start
UnmaskUnitFiles enable

表10.2 SELinux アクセスチェックでの systemd 一般システムコールのマッピング

systemd 汎用システムコール SELinux アクセスチェック
ClearJobs reboot
FlushDevices halt
Get status
GetAll status
GetJob status
GetSeat status
GetSession status
GetSessionByPID status
GetUser status
Halt halt
Introspect status
KExec reboot
KillSession halt
KillUser halt
ListJobs status
ListSeats status
ListSessions status
ListUsers status
LockSession halt
PowerOff halt
再起動 reboot
SetUserLinger halt
TerminateSeat halt
TerminateSession halt
TerminateUser halt

例10.1 システムサービスに関する SELinux ポリシー

sesearch ユーティリティーを使用すると、システムサービスのポリシールールを一覧表示できます。たとえば、sesearch -A -s NetworkManager_t -c service コマンドを呼び出すと以下が返されます。
allow NetworkManager_t dnsmasq_unit_file_t : service { start stop status reload kill load } ; 
allow NetworkManager_t nscd_unit_file_t : service { start stop status reload kill load } ; 
allow NetworkManager_t ntpd_unit_file_t : service { start stop status reload kill load } ; 
allow NetworkManager_t pppd_unit_file_t : service { start stop status reload kill load } ; 
allow NetworkManager_t polipo_unit_file_t : service { start stop status reload kill load } ;