Linux のセキュリティ機能の使い方のガイドラインを説明する前に, プログラマの観点からこれらの機能について知っておくと役に立つと思われる. この節では Linux のセキュリティ機能を簡単に説明する.これらの機能につ いて既に理解しているなら,次の節に進んでも構わない.
多くのプログラミングガイドは,Linux のセキュリティ関連の部分を切り詰め, 重要な情報を飛ばしている.特にこのようなガイドでは,何かの「使い方」の 一般的な内容は説明しているが,その使い方に影響を与えるセキュリティ属性 については体裁しか整えていないことが多い.その逆に,マニュアルページ には個々の関数についての詳しい情報が載っているが,マニュアルページでは 往々にして森の中に木が埋もれてしまうことになる. この節ではこのギャップの橋渡しを試みる.つまり,プログラマが使うと思わ れる Linux のセキュリティ機構の概要を説明する. この節では Linux のセキュリティ関連事項に特に注目して,普通の プログラミングガイドよりも深い話題を扱い,そしてさらに詳しい情報が得ら れるように参考文献を紹介する. UNIX のプログラマには馴染みがある分野だと思われるが,Linux における 拡張や Linux 固有の事情があるので驚くこともあるかもしれない. この節ではこのような相違点もできるだけ述べることにする.
まずは基礎を説明する. Linux は基本的に 2 つの部分に分けられる.すなわち Linux カーネル (カーネルモジュールを含む)と「ユーザ空間」である.ユーザ空間は カーネルの上にあり、様々なプログラムがここで動作する. ユーザがログインすると,そのユーザ名はそのユーザが所属する 「UID(user id の意味)」と「GID(group id の意味)」を表す整数値に割り当てられる. UID 0 は特殊な権限(役割)を持つユーザで,伝統的に「root」と呼ばれる. このユーザはほとんどのセキュリティチェックを越えることができ, システム管理のために用いられる. プロセスはセキュリティの点から見ると唯一の「主体」である(つまり, プロセスだけがアクティブなオブジェクトである). プロセスは様々なデータオブジェクト,特にファイルシステムオブジェクト (FSO, filesystem object),System V プロセス間通信(IPC)オブジェクト, ネットワークオブジェクトにアクセスできる. 次以降の節ではこれらを詳しく説明する.
Linux では,ユーザレベルの動作はプロセスの実行として実装されている. 多くのシステムは分離された「スレッド」をサポートしている.Linux では, 複数のスレッドが複数のプロセスを用いて実装されていることもある(この場 合,Linux カーネルはスレッドレベルの速度を得るための最適化を実行する).
全てのプロセスはセキュリティ関連の属性の集合を持っている.これを以下に 挙げる:
どの属性がそれぞれのプロセスに関連しているのかを正確に知る必要が本当に あれば,Linux のソースコードを調べること.特に include/linux/sched.h での task_struct を調べるとよい.
Linux バージョン 2.2 で「POSIX ケーパビリティ」の内部サポートが追加さ れた.POSIX ケーパビリティは,通常は root が持っている権限を,よ り細かい多数の権限に分割するといった機能に対応する. POSIX ケーパビリティは IEEE 標準のドラフトで定義されている.したがって, これは Linux 固有の機能ではないが,他の UNIX 的システムではあまり サポートされていない. Linux の文献(この論文も含む)に「root の権限を必要とする」と書かれてい るほとんど全ての場合は,実際には「ケーパビリティを必要とする」という意 味である.これはケーパビリティに関する文書に書かれている. 必要としている特定のケーパビリティについて知る必要があれば, ケーパビリティに関する文書で調べること.
最終的には,ファイルシステム内のファイルにケーパビリティを割り当て 可能にすることが目指されているが,この論文の執筆時点では,その機能にはまだ 対応していない. ケーパビリティの転送機能には対応しているが,この機能はデフォルトで無効 にされている. Linux のバージョン 2.2.11 には,ケーパビリティをより直接的に使いやすく する機能が追加された.この機能は 「ケーパビリティ限界集合(capability bounding set)」と呼ばれる. ケーパビリティ限界集合は,システム上の全てのプロセスが持つことが許され ているケーパビリティのリストである(許されていないケーパビリティは, 特殊な init プロセスだけが持てる). ケーパビリティが限界リストに載っていない場合は,特権を持っているかどう かに関係なく,どんなプロセスもそのケーパビリティを使用できない. この機能は例えば,カーネルモジュールの読み込みを無効にするときに使われ る. この機能を生かしたツールの例としては,LCAP ( http://pweb.netcom.com/~spoon/lcap/) が挙げられる.
POSIX ケーパビリティに関する詳しい情報は ftp://linux.kernel.org/pub/linux/libs/security/linux-privs で入手できる.
プロセスの生成には, fork(2), 使用が勧められない vfork(2),そして Linux 固有の clone(2) が使える.これらのシステムコール全ては,既にある プロセスを複製し,2 つのプロセスを作成する. プロセスは execve(2) とその各種フロントエンド(例えば exec(3), system(3), and popen(3) を参照)を呼び出すことによって別のプログラムを 実行できる.
プログラムが実行された時にそのファイルの setuid ビットか setgid ビット が立っていると,そのプロセスの EUID (setuid の場合)または EGID (setgid の場合)がファイルの値に設定される. Linux では,シェルスクリプト等の普通のスクリプトではこのような操作は行 われない点に注意すること.この操作をスクリプトに対して行うのは セキュリティ的な危険が多くあるからである(他の UNIX 的 OS には setuid したシェルスクリプトに対応しているものもある). 例外的に,Perl では setuid した Perl スクリプトに対応した設定を行える.
場合によっては,プロセスはさまざまな UID 値や GID 値に影響を及ぼすこと ができる.setuid(2), seteuid(2), setreuid(2), setfsuid(2) を参照すること. 特に SUID 属性は,信頼したプログラムが一時的に UID を切替えることを許す. RUID が変更された場合,または EUID に RUID と異なる値が設定された場合 には,SUID には新しい EUID が設定される. 特権を持たないユーザは,自分の SUID から自分の EUID を, RUID から EUID を,EUID から RUID を設定できる.
FSUID プロセス属性は,NFS サーバ等のプログラムに対し, ある UID の権限をファイルシステム関係のものに限って許可するためのものである。 その UID 権限でプロセスにシグナルを送ることはできなくする。 EUID が変更されると,FSUID は必ず新しい値に変更される.つまり, FSUID 値 は setfsuid(2) (Linux 固有のシステムコール)を使わなくても変わ る場合がある. root 以外からの呼び出しでは,FSUID には現在の RUID 値, EUID 値, SEUID 値, あるいは現在の FSUID 値しか設定できない.
ファイルシステムオブジェクト(FSO)は通常ファイル,ディレクトリ, シンボリックリンク,名前付きパイプ(FIFO),ソケット, キャラクタ特殊(デバイス)ファイル,ブロック特殊(デバイス)ファイルのいず れでもよい(このリストは find(1) コマンドで表示される). ファイルシステムオブジェクトはファイルシステム上に集められる. ファイルシステムは親となるファイルシステム上のディレクトリに マウント/アンマウントできる. ファイルシステムはファイルと少し異なるアクセス制御属性を持ち, アクセス制御はマウント時に選択したオプションの影響を受ける.
現在 ext2 は Linux システムで最もよく使われているファイルシステムであ る.ext2 ファイルシステムは各ファイルシステムオブジェクトに対して 以下の属性をサポートしている:
以上の値の多くはマウント時に影響を受ける.つまり,例えば, (メディア上に保持している値に関係なく)あるビットがある特定の値を持って いるかのように扱われることがある. 詳しい情報については mount(1) を参照すること. ファイルシステムによっては,一部のアクセス制御値をサポートしていないこ とがある.繰り返しになるがこのようなファイルシステムの扱いについては mount(1)を参照すること.
アクセス制御リスト(ACL, access control list)と POSIX ケーパビリティ値 をファイルシステムに追加する作業が現在行われているが,この機能は 普通 の Linux 2.2 には入っていない.
ファイルシステムオブジェクトの生成時には以下の規則が適用される. ファイルシステムオブジェクト(FSO)が(例えば creat(2) を使って)生成され たとき,その FSO の UID には,FSO を生成したプロセスの FSUID が設定さ れる.普通は FSO の GID には,FSO を生成したプロセスの FSGID が設定 されるが,FSO が作られるディレクトリの setgid ビットが設定されている 場合や,ファイルシステムの「GRPID」フラグが設定されている場合には, FSO の GID にはこのディレクトリの GID が設定される. この特殊なケースを使うと「プロジェクト」ディレクトリに対応できる. つまり,「プロジェクト」用のディレクトリを作り,そのプロジェクトのため の専用のグループを作り,そのグループが所有するプロジェクトのための ディレクトリを作ってから,そのディレクトリに setgid を設定する. すると,このディレクトリに作成されたファイルは自動的にプロジェクトのも のとなる. 同様に,setgid ビットが設定されている(そしてファイルシステムの GRPID が設定されていない)ディレクトリ内に新しくサブディレクトリを作ると, そのサブディレクトリの setgid ビットも設定される(したがって, プロジェクトのサブディレクトリも「正しく」動作する).それ以外の場合に は全て,新しいファイルの setgid ビットはクリアされる. FSO の基本的なアクセス制御値(読み取り,書き込み,実行)は (要求された値 & ~ プロセスの umask 値)によって求められる. 新しいファイルが作られたときは,sticky ビットと setuid ビットは 必ずクリアされた状態になっている.
アクセス制御属性のほとんどは chmod(2) や chmod(1) で設定できる.ただし, chown(1), chgrp(1), chattr(1) も参照すること.
Linux では,あるファイルの所有者を変更できるのは root だけである点に注 意すること.一部の UNIX 的 OS には一般ユーザが所有権を変更できるものが あるが,これは扱いが面倒になる.例えばディスクの使用量を制限しようとし た場合,一般ユーザに所有権の変更を許していると,大きなファイルは 誰か別の「被害者」のもののようにできてしまう.
Linux およびほとんどの UNIX 的 OS では,属性値の読み書きはファイルを オープンしたときにしかチェックされない.つまり,一度ファイルをオープン した後は読み書きするたびの再チェックは行われない. これらの属性値をしているシステムコールは非常にたくさんある.なぜなら, ファイルシステムは Linux の中心にとても近い部分にあるからである. このようなシステムコールには open(2), creat(2), link(2), unlink(2), rename(2), mknod(2), symlink(2), socket(2) 等がある.
長年の伝統により「どのファイルをどこに置くか」という約束ごとができている. 情報をファイル階層内に配置するときには,この決まりに従うこと. この決まりには hier(5) にまとめられている. さらに詳しい情報は Filesystem Hierarchy Standard (FHS) として入手できる. この規約は,以前に存在した Linux Filesystem Structure standard (FSSTND) を改めたものである.詳しくは http://www.pathname.com/fhs を参照すること.
Linux は System V IPC オブジェクト,すなわち,System V のメッセージ キュー,セマフォセット,共有メモリセグメントに対応している. これらのオブジェクトはそれぞれ以下の属性を持っている:
このようなオブジェクトにアクセス際に適用される規則は以下の通りである:
root が実行したプロセスまたは所有者か作成者の EUID を持つプロセスは, 所有者 UID と所有者 GID を設定したり,オブジェクトを削除できる. 詳しい説明が ipc(5) にある.
ソケットは通信,特にネットワーク通信で用いられる. socket(2) は通信用の端点(endpoint)を作成し,デスクリプタを返す. 詳しくは socket(2) や,その他の関連情報を参照すること. Linux では,TCP と UDP を 1024 番未満のローカルポートに割り当てるには root 権限が必要な点に注意すること(1024 番未満のリモートポートに割り当 てる場合には特別な権限は必要ない).
Linux にはファイルシステムの quota とプロセスのリソース制限を行うため の機構がある. ここでは用語に注意すること.というのも,quota とリソース制限には 「ハードな」制限と「ソフトな」制限があるが,これらの用語は少し違う 意味を持つからである.
記憶装置(ファイルシステム)の quota 制限を各マウントポイントごとに定義 できる.定義は,指定されたユーザかグループが使用できる 記憶装置のブロック数か,ユニークなファイル数(inode の数)について行う. 「ハード」な quota 制限は決して超えることができない制限であるが, 「ソフト」な quota 制限は一時的に超過することが許される. 詳しくは quota(1), quotactl(2), quotaon(8) を参照すること.
rlimit 機構は,プロセスに対する非常に多くの種類の quota に対応している. 例えばファイルサイズ,子プロセスの数,オープンできるファイルの数などで ある. 制限には「ソフトな」制限(現在の制限(current limit)とも呼ばれる)と「ハード」 な制限(上限(upper limit)とも呼ばれる)がある. ソフトな制限を超えることはどんな場合も許されないが,ソフトな制限値は システムコールを使ってハードな上限値まで上げることができる. 詳しくは getrlimit(), setrlimit(), getrusage() を参照すること.
現在もっとも一般的な「監査」機構は syslogd(8) である. wtmp(5), utmp(5), lastlog(8), acct(2) も見ると良いだろう. サーバプログラムによっては(例えば WWW サーバの Apache 等)は,独自の 監査機構も備えている.
認証を行う際,ほとんどの Linux システムでは PAM (Pluggable Authentication Modules, 差し替え可能な認証モジュール) が用いられる.PAM を用いると認証の設定を行うことができる(例えば パスワードの使用,スマートカードの使用など). PAM については,この論文の後の方で詳しく説明する.