up スクリプトを root で実行すると完了しますが、同じスクリプトをサービスが呼び出すと失敗します。ファイルの権限は何も変わっていないので、次に緩めようとするのは自然ですが、それでは何も直りません。SELinux のホストでは、決定する要因はプロセスが誰かではなく、どのドメインで動いているかであることが多く、制限されたドメイン内の root も制限されたままです。

同じコマンド、二つの異なるセキュリティドメイン

型強制は、送信元ドメイン、対象ラベル、要求された操作をまとめて評価します。ターミナルのセッションは制限なしまたは管理用のドメインで動き、デーモンはユニットに割り当てられたドメインで動きます。そのため同じコマンドでも判断が変わり、この違いはポリシーの不具合ではなく意図されたものです。

だからこそ、二つの実行の比較は文脈を比べたときにだけ役に立ちます。同じコマンドをシェルからもフックからも実行すると、シェル側はバイナリが存在し引数が正しいことを示しますが、サービスに実行が許されているかは何も示しません。両方の方法で実行し、終了コードだけでなくドメインを比べてください。その比較が、曖昧な許可の不満を、一つのドメインと一つのラベルに関する具体的な問いに変えます。

この不具合の典型的な形は、外部ツールを呼び出すヘルパーです。フック自体は許可されていても、呼び出すツールにサービスドメインが実行できないラベルが付いている、あるいはラベルが禁じるディレクトリに書き込んでいることがあります。

フックのエラーの隣にある AVC レコードを読む

AVC の拒否は、判断を決める項目を示します:プロセスの送信元コンテキスト、オブジェクトの対象コンテキスト、オブジェクトクラス、そして拒否された具体的な許可です。実行の拒否と書き込みの拒否では修復がまったく異なるため、理論を立てる前に四つすべてを読みましょう。

ausearch -m AVC,USER_AVC -ts recent
ls -Z /usr/local/sbin/vpn-up.sh
ps -eZ | grep openvpn

送信元コンテキストはサービスが実際に動くドメインと、対象コンテキストは操作が触れたファイルやディレクトリのラベルと一致するはずです。どちらかが追っているエラーと合わないなら、別のイベントを読んでいます。

レコードのそばに、ポリシーのバージョンと実行ファイルの正確なパスを書き留めます。あるディストリビューションのポリシーに現れるドメイン名は、そのインストールについての証拠であり、別のビルドが同じルールを同梱する保証ではありません。この文脈があるからこそ、他の人が自分のホストで同じ結論を再現できます。それがなければ、レコードは証拠ではなく逸話として読まれます。

ラベル、設定、ポリシー:三つの修復

第一の修復は、ファイルのインストール位置と合わないラベルです。cp で所定の場所にコピーしたスクリプトや、エディタで書いたスクリプトは、サービスドメインが使えない既定のラベルを持つことがあり、期待されるコンテキストを戻せばポリシーに触れずに直ります。

第二は設定です。ディストリビューションが、操作を実行するサポートされた方法、ヘルパー用の文書化されたディレクトリ、あるいはすでに許可している更新済みのポリシーパッケージを提供しているかもしれません。レイアウトをサポートされた形に変えるほうがポリシーを書くより安く、更新にも耐えます。

第三は本当に欠けているルールで、最後の手段であるべきです。監査ツールで候補を生成し、実際に何を許可するかを読み、観察した操作とドメインに絞り込み、本番に近づく前に他の人にレビューしてもらいます。

古い allow モジュールが答えにならない理由

この不具合の検索結果は既製のモジュールで溢れており、しばしばフックがもう呼ばないツール向けです。一つ入れると、あなたの拒否と無関係な許可が与えられ、本当の不一致を残したまま恒久的な穴を追加します。

次の失敗も隠します。広い種類の操作を許可するモジュールは、このエラーを消し、次のエラーを遥かに原因を特定しにくいものに変えます。後からモジュールを外すのも誰も予定したくない変更なので、近道は恒久化しがちです。

規律ある比較とは、読める拒否と提案する変更の間の比較です。Red Hat の SELinux のトラブルシューティングガイド は、まさにこの理由で、ラベルと設定の確認を生成されたポリシーより前に置いています。レコードに対応する拒否がなければ、SELinux はおそらくあなたの問題ではなく、パス、サンドボックス、許可の問題は依然として開いたままです。

関連記事