第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
システムチェックが呼び出されます。
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 |
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 } ;