Linux Security Module

巷では、SONY BMGのrootkit問題が騒がれているようだが、Linuxカーネルにとっても、kernel rootkitの脅威が今でもあることには変らない。カーネルのセキュリティ対応というと、以前このコラムで紹介されたExec ShieldやNXビット対応、カーネル2.6でメインラインにマージされたSELinuxなどがあるが、今回は最近のLKMLへの投稿で増えてきた、LSM(Linux Security Module)に関する話題を取り上げてみる。

カーネルにセキュリティ機構を導入する手法として、以前から一般的だったSELinuxExec Shieldなどは、いずれもカーネル全体を改造するPatch形式で提供されるものだった。ところがカーネル2.6になってからは、LSM(Linux Security Module)が標準で導入され、セキュリティ関連のエンハンスメントが容易にできるようになった。本題に入る前に少し整理してみる。

SELinux

米国NSA (National Security Agency) が中心になって開発して、GPLで配布している Linux のセキュリティ拡張モジュール。Linuxの「何でも実行できるモード」しかないカーネルにパミッションの概念を導入して、カーネル自体を外部からの侵入や不正な処理の実行を防ぐよう、セキュアにすることを目的にして現在でも開発が進められている。当初は2.2系カーネルのPatchとして提供されていたが、現在ではカーネル2.6のセキュリティ機能拡張用標準インタフェイスである LSM (Linux Security Module) に準拠している。

LSM (Linux Security Module)

Linuxカーネル2.6に新機能として付加(実際は2.5から開発)されたセキュリティ機能拡張用標準インタフェイス。フックと呼ぶ、主要なカーネル内操作の実行時に呼び出す、コールバック関数をフレームワークとして用意している。これによりカーネル自体を改造せずに、セキュリティ機能を提供するモジュールを自由に開発し、組み込ことができるようになった。SELinuxも、このLSMに対応したモジュールとして、カーネル2.6に組み込まれている。

[PATCH] Keys: Export user-defined keyring operations

David Howellsは、古くからカーネルの開発に寄与していて、今まで主にNFSを始めとするファイルシステム関連の開発を担当していたが、最近ではLSM関連の開発も行っている。10月5日にDavidは、「Keys: Export user-defined keyring operations」と題したPatchを、LKMLに投稿した。

添付のPatchは、ユーザー定義のKEY操作に基づいた、自分のキータイプを(要求された場合に)定義できるように、ユーザー定義のKEY操作をエクスポートするものである。include/keys/user-type.hに、作成したヘッダファイルがあり、それで他のキータイプを置く場合がある場合には、ディレクトリを作成する。何か反対意見はないだろうか?

Patchを見て、Davidと同じRedhatのArjan van de Venが言った。

これは新しいlinuxユニーク(unique-to-linux)な機能なので、_GPLでエクスポートすることをどうか考慮して欲しい。(訳注:Arjanの言うように、EXPORT_SYMBOL_GPL()でエスクポートすると、GPLの外部モジュールだけででしか利用できなくなる)

しかしJames Morrisは、EXPORT_SYMBOL_GPL()とEXPORT_SYMBOL()の違いについては、正しく理解していなかった。そこでLinus Torvaldsが言った。

私は二人の弁護士と話したのだが、これらには絶対的に*大きな*差がある。また、そうあるべきである。

事実として、法律は「文字通りのことを受け取る」ような、盲目で無関心なコンピュータではない。深刻な課題が山のようにある。そして、それがカーネルの内部インタフェイスであることを示すために、xxx_GPL()バージョンを使用することは、大きな意味が確かにある。

弁護士のうちの一人は、それがライセンスの一部始終について説明するより、はるかによいアプローチであると言った。コード自体の意図を成文化することは、より柔軟になるだけでなく、誤解を全て回避することができるからだ。

また、二人ともがそう言ったと思うのだが、非GPLモジュールとともに使用するために、xyz_GPLをnon-GPLのものに変更することを企んだ誰でもが、直ちに「故意の侵犯」とみなされることになるだろう。しかもそれから、3倍の損害賠償命令を得ることを*はるかに*簡単にするだろう。

私は、プログラマが健全な人間がしないような些細な欠点のあら捜しまでをする、恐るべき弁護士を作り出して行くのではないかと思う。プログラマは結局のところ、人間の対話という手段が機能しない事実について、時には忘れてしまうのではないだろうか。常識というのでは多くの間違いを生じるし、DWIM(訳注:Do What I Mean=私が言った通りに動け=思い通りに動作しないプログラムに対する嘆き)は可能ではない。そして重要なことは、ただ一つしかない。

Arjan van de Venは、要求にすぐに対応して貰えなかったので、勝手にEXPORT_SYMBOL_GPL()に書き換えたPatchを作ってLKMLに流して、David Howellsに了解を求めた。

[PATCH] Keys: Add LSM hooks for key management

続いてDavid Howellsは、「[PATCH] Keys: Add LSM hooks for key management」というタイトルのメールをLKMLに投稿した。同じ日のことである。

添付のPatchは、KEY管理機能用のLSM(Linux Scurity Module) フックを加える。注目すべき修正点は次の通りである:
  1. KEYの構造体は、セキュリティモジュールが使用するための、セキュリティポインタをサポートする。これはKEYのラベル付けを行い、プログラムがKEYにアクセスする場合の利用制限の許可を行う。
  2. セキュリティモジュールは、KEYの割当てを中止する場合がある。
  3. KEYにセキュリティデータを関連付けさせ、それを検索するための2個の新しいkeyctl関数を付加した。それらは、セキュリティモジュールに直接接続するだけで、他の機能は持たない。
  4. KEYのパミッションチェックは上書きするか、あるいはセキュリティモジュールによって機能拡張することができる。またソース中、大きくて頻繁に使用している部分は、key-ui.hファイルからpermission.cファイルに移動した。
  5. セキュリティモジュールは、KEYを証明するか更新するかして、データをレビューする場合がある。

注意点:特に各keyctl()操作のためのLSMフックがないことに注意すること。しかしパミッションのフックは、パミッション要求ビットに基づいた個別操作の制御を許可する。

LSMによるKEY管理のアクセス制御はCONFIG_SECURITY_KEYSによって可能になる。

James MorrisもまたRedhatに所属しているが、むしろSELinuxの主要開発メンバとして有名である。これを見て、そのJames Morrisはそのパッチが非常に気に入ったようだった。彼は尋ねた、なぜわざわざそれを(カーネルで)コンフィグ可能にしたのだろうか。

Davidはそれに対して、Networkのような他の構成要素がそうだったので単に従っただけで、コンフィグ不可にもできると言った。さらに、彼が利用可能にしたキー用のセキュリティ操作に関する評価を求めた。それに対してJamesが答えた。

以前、LSMの内部からのNetfilterのフックを登録した時などは特にそうだったが、確かにNetwork関連では性能重視のために、コンフィグ不可を検討すべきである。私は、LSMを可能にするが、ネットワーキングを無効にするディストリビューションがあるかについては知らない。したがって、いずれにしても恐らくそれの削除することに関してだけは、考えておくべきだと思う。セキュリティ操作については、SELinuxの視点から見てこれを見る必要があり、時間がかかるのでよくわからない。

翌日、改めてJamesが言った。

私は、ファイルのような不明瞭なオブジェクトとしてキーを扱う場合、SELinuxの視点から見てこの手法はOKだと思う。

KERNKEY、または何かそのような新しいオブジェクトクラスを作り、READ, WRITE, SEARCH, LINK, SETATTR, GETATTRといったSELinuxのパミッションを実装することで、何でも実行することができる。また、KEY_VIEWのパミッションをSELinux のGETATTRに翻訳することができる。

プロセスが匿名のKEYRINGを作成することに対するコントロールのために、パミッションを作成するSELinuxを実装する必要があるか、またコードへフックを加えかどうかについて、より多くの考えを検討する必要がある。

LSPP(Labeled Security Protection Profile)はget_securityのいくつかの形式を要求する場合があるが、私はset & get security opsによってKEYのユーザレベルのラベル付けを必要とするかどうか分からない。我々が手動でセキュリティ属性をセットするだけではなく、それらをさらに監視する必要があるならば、個別の多重syscallを実装するのではなくて、/proc/keysによってそれらを表示する場合がある。

下記に対応するLSMのチェックは無いのではないかと思う。

  • keyctl_chown_key()
  • keyctl_setperm_key()
  • keyctl_set_reqkey_keyring()
  • keyctl_join_session_keyring()  (もし ‘create’ パミッションが付加されたならば)

key_permission()のユーザはみな、ユーザにLSMからのエラーコードを広める必要がある。

この後も、細かい実装のやりとりが続いたのだが、それらは別の機会に紹介する。

※2005年11月28日、LSPPのリンクを追加。