第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 としても機能するようになりました。これは、D-Bus メッセージを systemd に送信するプロセスや systemctl を実行しているプロセスのラベルを取得することができます。このデーモンはその次にプロセスが設定を希望するユニットファイルのラベルを探します。最後に、SELinux ポリシーがプロセスラベルとユニットファイルのラベルの間で特定のアクセスを許可する場合、systemd はカーネルから情報を取得することができます。つまり、特定のサービスについて systemd と対話する必要のあるアプリケーションで危険にされされているものは、SELinux で制限ができるようになっています。ポリシー作成者は、これらの細かい制御を使って管理者を制限することができます。ポリシー変更には service と呼ばれる新たなクラスが関わり、以下のパーミッションを伴います。
class service
{
       start
       stop
       status
       reload
       kill
       load
       enable
       disable
}
たとえば、ポリシー作成者はドメインがサービスの状態を獲得したり、サービスを開始、停止することを許可できるようになりましたが、サービスを有効、無効にすることはできません。SELinux および systemd でのアクセス制御の操作は、すべてのケースで一致するわけではありません。マッピングは、systemd メソッド呼び出しと SELinux アクセスチェックが並ぶように定義されています。表10.1「systemd ユニットファイルメソッド呼び出しと SELinux アクセスチェックのマッピング」では、ユニットファイルにおけるアクセスチェックのマッピングを表示しています。表10.2「systemd の全般的なシステム呼び出しと SELinux アクセスチェックのマッピング」では、システム全般におけるアクセスチェックを表示しています。これらの表で一致するものがない場合は、undefined システムチェックが呼び出されます。

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

systemd ユニットファイルメソッドSELinux アクセスチェック
DisableUnitFilesdisable
EnableUnitFilesenable
GetUnitstatus
GetUnitByPIDstatus
GetUnitFileStatestatus
Killstop
KillUnitstop
LinkUnitFilesenable
ListUnitsstatus
LoadUnitstatus
MaskUnitFilesdisable
PresetUnitFilesenable
ReenableUnitFilesenable
Reexecutestart
Reloadreload
ReloadOrRestartstart
ReloadOrRestartUnitstart
ReloadOrTryRestartstart
ReloadOrTryRestartUnitstart
ReloadUnitreload
ResetFailedstop
ResetFailedUnitstop
Restartstart
RestartUnitstart
Startstart
StartUnitstart
StartUnitReplacestart
Stopstop
StopUnitstop
TryRestartstart
TryRestartUnitstart
UnmaskUnitFilesenable

表10.2 systemd の全般的なシステム呼び出しと SELinux アクセスチェックのマッピング

systemd の全般的なシステム呼び出しSELinux アクセスチェック
ClearJobsreboot
FlushDeviceshalt
Getstatus
GetAllstatus
GetJobstatus
GetSeatstatus
GetSessionstatus
GetSessionByPIDstatus
GetUserstatus
Halthalt
Introspectstatus
KExecreboot
KillSessionhalt
KillUserhalt
ListJobsstatus
ListSeatsstatus
ListSessionsstatus
ListUsersstatus
LockSessionhalt
PowerOffhalt
Rebootreboot
SetUserLingerhalt
TerminateSeathalt
TerminateSessionhalt
TerminateUserhalt

例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 } ;

このページには機械翻訳が使用されている場合があります (詳細はこちら)。