著者:コーリー・ミニヤード、モンタビスタ・ソフトウェア
第4章:政策全体の構造
前の章では、ポリシー ファイルで OpenWRT ポリシーsrc使用する方法について説明しました。しかし、大きなポリシー ファイルは 1 つではなく、かなり一貫した方法で個別のファイルに分割されています。`src` ディレクトリを見ると、` cilで終わるファイルがたくさんあり、` cilファイルと同じ名前のディレクトリもいくつかあります。これはポリシーの一貫したテーマであり、理解しておくことが重要です。ディレクトリには特定のサブクラスまたはオブジェクトが含まれており、` cilファイルはそれらのオブジェクトのベース クラスになります。これは、ディレクトリ構造 (` /varは ` varfile.cilに、` /var/runは ` varfile/runtimevarfile.cilにあります) に関係することもありますが、より一般的には機能に関係しています。
fs
` fsクラスは、一般的にマウントされるファイルシステムに関係するものです。必ずしもマウントされている必要はありませんが、ほとんどの場合 ` / ` にあります。
これらはファイルシステムへの基本アクセスに使用します。` /tmpを検索するためのアクセスが必要な場合は、` fs/seclabelfs/tmpseclabelfs.cilを参照してください。` /tmpにファイルを作成できるようにするには、ブロック ` tmpが ` .fs.obj_file_macro_templateを継承していることがわかります。このテンプレートには、マクロとして ` addname_fs_dirsが含まれています。したがって、以下を追加できます。
(call .tmp.addname_fs_dirs (subj))
エージェントのブロックに/tmpにファイルを作成できるようにします。
` fsは、通常のセキュリティラベルを持つファイルシステム用の` seclabelfsと、完了したファイル(DOS、ISO9660、proc、SELinuxなど)用の` noseclabelfsという2つの主要なサブクラスがあります。
xxxファイル
` srcディレクトリには、このパターンに一致するファイルがたくさんあります。また、これらの多くが ` fsディレクトリにあるものと一致することにも気づくでしょう。これは意図的な設計であり、これらのクラスは特定のディレクトリにあるファイル用です。
ファイル
` fileクラスはファイルの種類を扱います。これは場所というよりも機能に関するものです。例えば、実行可能ファイルは ` file/execfile.cilで処理されます。ファイルを作成する場合、またはエージェントがファイルを使用する場合は、これらのいずれかの型で表現する必要があります。
独自のコンテキストを作成する場合は、ファイルの目的に応じて、ファイルディレクトリにあるクラスのいずれかを使用してこれを行う必要があります。
` file.cilは、すべてのクラス権限と、すべての権限に関する基本的なクラス情報も作成します。
ファイルアクセスの例
` /tmpディレクトリに ` asdfというファイルを作成したいとします。エージェントがアクセスと保護を維持できるように、このファイルにラベルを付けたいとします。これはデータファイルです。まず、データファイルを扱うためのマクロを作成しましょう。エージェントの名前を myagent とし、その名前のブロックがあるとします。エージェントブロックに以下を追加します。
; Create macros and types for accessing our data files<br /> (blockinherit .file.data.obj_template)
これにより、ブロック内に` datafile_file_contextが作成されます。次に、fileconエントリを追加します。
(filecon<br /> "/tmp/asdf"<br /> file<br /> datafile_file_context)
そのファイルに適切なラベルを付けるには、手動でファイルを作成すると、` /tmpディレクトリ内のファイルに付けられるラベルである ` u:r:tmp.fsというラベルが付けられます。これは ` src/fs/seclabelfs/tmpseclabelfs.cilで確認できます。このファイルを調べて、すべてのブロック継承をたどって遷移ルールを見つけることができます。それはブロック tmp にあるので、以下を追加します。
(macro obj_type_transition_datafile ((type ARG1))<br /> (call .tmp.fs_obj_type_transition<br /> (ARG1 datafile file "asdf")))
これにより、ファイルの適切なラベル付けを保証するために使用するマクロが作成されます。先頭のエージェントブロックの外側に、以下を追加してください。
(in .file<br /> (call myagent.obj_type_transition_datafile (unconfined.subj_typeattr))<br /> )
これは、適切なラベルが付いたファイルを作成するために、そのマクロを使用します。つまり、tmpseclablfs.cil のルールに従って、unconfined から ` u:r:tmp.fsに移行し、その後、上記のルールに従って ` u:r:myagent.datafileに移行します。
基本的な原理は、オブジェクトの作成時に、ルールに基づいてオブジェクト型の遷移が1つのコンテキストから別のコンテキストへと移行するというものです。オブジェクト型の遷移の連鎖をたどることで、最終的な型を見つけることができます。
次に、ファイルへのアクセス権が必要です。エージェントブロックに以下を追加してください。
; We create/delete /tmp/asdf<br /> (call .tmp.readwrite_fs_dirs (subj))<br /> (call manage_datafile_files (subj))
最初の呼び出しでは/tmp内のファイルの作成と削除が可能です。代わりに ` manage_fs_dirsを使用することもできますが、これは必要以上の権限 (名前変更など) を付与します。必要最小限の権限を使用してください。2 番目の呼び出しでは、` blockinheritで作成されたマクロを使用してデータ ファイルにアクセスします。
しかし、これで終わりではありません。この手順をすべて実行しても、プログラムが ` /tmp/asdfを作成する際には、` u:r:myagent.datafileコンテキストではなく、` u:r:tmp.fsコンテキストになります。ただし、制約のないシェルから作成する場合は、正しく動作します。これは、追加した型遷移で、` unconfinedが遷移を実行できるようにしたためです。
現在、` myagent.subjにはこの操作を行う権限がありません。そのため、myagent ブロックに次のルールを追加します。
; Allow myagent.subj to transition our file in /tmp/asdf<br /> (call obj_type_transition_tmpfile (subj))
すべてうまくいくはずです。
例:新しいディレクトリ
ここで、` /var/lib/myagentというディレクトリを作成したいとします。検索すると、` /var/libは ` src/varfile/statevarfile.cilにあることがわかります。そのため、このファイルとやり取りする必要があります。まず、そこからクラスを継承します。
(blockinherit .varfile.state.obj_template)
そして、ファイルに対応する` fileconエントリが必要です。
(filecon<br /> "/var/lib/myagent"<br /> dir<br /> statevarfile_file_context)<br /> (filecon<br /> "/var/lib/myagent/.*"<br /> any\<br /> statevarfile_file_context)
ファイルを作成する際には、状態遷移のためのマクロが必要です。
(macro obj_type_transition_statevarfile ((type ARG1))<br /> (call .varfile.statevarfile_obj_type_transition<br /> (ARG1 statevarfile dir "myagent")))
そして、ファイルブロック内でそれを呼び出す必要があります。
(in .file<br /> (call myagent.obj_type_transition_statetmpfile<br /> (unconfined.subj_typeattr))<br /> )
そしてもちろん、ファイルへのアクセスも必要です。
; Access to /var/lib/myagent. We grant full access.<br /> (call manage_statevarfile (subj))
これはよく見かけるごく一般的なパターンです。
` myagent.subjが適切なコンテキストでファイルを作成できるようにするために、オブジェクトタイプの遷移はおそらく必要ありません。ただし、プログラム自体から ` /var/lib/myagentを作成している場合は別です(その場合、restorecon によるラベル付けは適用されません)。これは、` /var/lib/myagentは既に restorecon によって適切にラベル付けされているため、その下に作成されたものはすべてそのラベルを継承するからです。
エージェント
エージェントとは一般的に、プログラムまたはプログラムの集合を指します。`agent.cil` agent.cilはエージェントの基本クラス情報が含まれており、当然のことながら、` agentディレクトリにはすべてのエージェントが格納されています。
対象
` subj.cilは、サブジェクトを処理するためのマクロとテンプレートが含まれています。また、サブジェクトのパーミッションを処理するためのクラスパーミッションなどもすべて作成します。これらはすべて非常に分かりやすいものです。これらの詳細については、他のSELinuxドキュメントを参照してください。
file_contexts.subs_dist
メインディレクトリ(srcディレクトリではない)にこのファイルがあります。これはディレクトリ名の置換リストです。例えば、以下のような内容が含まれています。
/bin /usr/bin
つまり、` fileconの観点からは、 /binにあるものはすべて/usr/binにあるものとして扱います。これにより、実質的に同等のものに対して大量の ` fileconエントリを作成する必要がなくなります。
` xxx_typeattrと「all」を含むマクロは何を意味するのでしょうか?
いくつかのブロックには、似ているようで少し異なるものが含まれていることに気づくかもしれません。たとえば、` src/varfile.cilには次のものがあります。
(macro readwrite_varfile ((type ARG1))<br /> (allow ARG1 varfile (allfiles (readwrite))))
また、.file.obj_all_macro_template から継承されるため、次のようになります。
(macro readwrite_all ((type ARG1))<br /> (allow ARG1 obj_typeattr (allfiles (readwrite))))
唯一の違いは、obj_typeattr と varfile です。以下の違いは何でしょうか?
(call .varfile.readwrite_varfile (subj))
そして
(call .varfile.readwrite_all (subj))
obj_typeattrは型属性ですが、あまり適切な名前ではありません。実際には、型グループ、または型の集合体に近いものです。1 つ以上の型を含めることができ、これを使用することは、それらの型すべてをその場所に配置するようなものです。このポリシーでは、これを型クラスのように使用します。したがって、` .varfile.obj_typeclassは ` /varと ` /var内のすべて、つまり ` .varfile.varfileから派生するすべて (` /var/runや ` /var/libなど) であり、` .varfile.runtimevarfile .varfile.varfile ` .varfile.statevarfileなどが含まれます。
` varfileまたは ` .varfile.varfileを完全に参照した場合、その参照は特定の型のみを対象とします。そのため、そのアクセス権があれば、` /var内のファイルや、その特定のコンテキストを持つファイルを直接参照できますが、コンテキストが異なる/var/run内のファイルを開くことはできません。
では、どちらを使うべきでしょうか?
最善策は、可能な限り最も制限の厳しいものを使用することです。` /var/runと ` /var/libへのアクセスは必要だが ` /var/logへのアクセスは不要な場合は、` .varfile.obj_typeattrを使用しないでください。これはセキュリティ上のベストプラクティスではありません。具体的には、以下の操作は行わないでください。
(call .file.manage_all (subj))
あるいは、そのような類のものでもありません。そうすれば、あらゆるものに完全にアクセスできてしまい、確かに簡単にはなりますが、逆効果になるでしょう。
場合によっては` subj_typeattrという引数もありますが、あまり使われることはありません。基本的な原理は同じで、対象がプロセスだけです。
結論
この概要を読めば、この問題に取り組むためのいくつかのツールが得られるはずですが、それでも苦労するでしょう。
CILファイルを詳しく調べ、ブロックをgrepで検索し、その内容を確認するなど、ある程度の時間をかける必要があります。MontaVistaのSELinuxに関する顧客事例についての私のブログ記事が、私が最初に乗り越えなければならなかったハードルを皆さんが克服するのに役立つことを願っています。
#selinux IRCチャンネルとSELinuxメーリングリストでは、手厚いサポートが受けられます。皆、喜んであなたの疑問を解決してくれるでしょう。組み込みセキュリティに関する質問や技術サポートが必要な場合は、MontaVistaに問い合わせることもできます。
MVSecureサービスとMVXpertサービスの詳細については、こちらをご覧ください。
Please reach out to discuss your particular scenario today.