3.2. ファイル

すべての Unix ライクなシステムは、「/」を情報が保存されている大元とし、そこ から広がる形でファイル木構造をつくっています。 ファイル木構造はディレクトリを階層化していて、そのぞれぞれがファイルシステム のファイルシステム・オブジェクト(FSO)を持っています。

Linux においては、ファイルシステムのオブジェクト(FSO)には通常のファイルや ディレクトリ、シンボリックリンク、名前つきパイプ(ファーストイン・ファースト アウトと言ったり、FIFO と言ったりします)、ソケット(下記を参照してください)、 キャラクタスペシャル(デバイス)ファイル、ブロックスペシャル(デバイス)ファイル 等があります(Linux では find(1)コマンドにその一覧があります)。 その他の Unix ライクなシステムでもまったく同じ、もしくは似たような FSO の一覧 があります。

ファイルシステム・オブジェクトは、ファイルシステム上に存在し、ファイル木構造 にあるディレクトリにマウントしたりアンマウントしたりします。 ファイルシステムのタイプ(たとえば ext2 や FAT)とは、ディスク上にデータを配置 し、速度や信頼性等を最適化する、特定の約束事です。 「ファイルシステム」という用語をファイルシステムの種類と同じ意味で使う場合 もよくあります。

3.2.1. ファイルシステム・オブジェクトの属性

ファイルシステムのアクセス制御の属性は多少変わっていて、アクセス制御は マウント時に選択したオプションに左右されます。 Linux では、ext2 がファイルシステムとしては現状最も一般的ですが、おびただしい 数のファイルシステムをサポートしています。 たいていの Unix ライクなシステムも、複数のファイルシステムをサポートして います。Unix ライクなシステムは、それぞれで複数のファイルシステムのタイプを サポートしています。

Unix ライクなシステムの多くは、少なくとも下記の情報を記録しています。

下記は、ext2 ファイルシステムを使っている Linux 独自の属性になります。 しかし、同じ機能を持った他のファイルシステムもたくさんあります。

  • 変更不可(immutable)ビット――ファイルシステム・オブジェクトに対して、いかなる 変更も認めません。 root だけが設定と解除ができます。 この仕組みは、ext2 ファイルシステムだけがサポートしており、すべての Unix システム(場合によっては Linux ファイルシステムでも)で利用できるわけでは ありません。

  • 追加限定(append-only)ビット――許可されるのは、ファイルシステム・オブジェクト の追加だけです。 root だけが設定と解除ができます。 この仕組みは、ext2 ファイルシステムだけがサポートしており、すべての Unix システム(場合によっては Linux ファイルシステムでも)で利用できるわけではあり ません。

拡張機能で他に一般的なものは、「このファイルを消せない」ことを示すビットです。

上記の値は、マウント時に適用される場合が多いので、あるビット値が既に 値(媒体上の値が何であれ)を持っていたかのように扱われる場合もあります。 詳しいことは mount(1)を参照してください。 これらのビットは役に立ちますが、注意する必要があります。それは平易で使い やすいこと、ある行為を防げるのに十分なことです。 たとえば、Linux においてはマウントする時に「noexec」すると、そのファイル システム上ではプログラムの実行ができなくなります。man にも記述してある 通り、これはそのシステムと互換性のないシステムで動くバイナリがあるファイル システムをマウントしようとする場合に使います。 Linux では、このオプションで誰かがファイルを実行することを完全には防ぎ きれません。 そのファイルをどこかにコピーし、そこで実行できてしまいますし、 「/lib/ld-linux.so.2」というコマンドを使って、そのファイルを直接実行 できてしまうからです。

ファイルシステムには、これらのアクセス制御に対するビット値をサポートして いないものもあります。繰り返しますが、mount(1)を見て、ファイルシステムが どのように扱かわれるのか確認してください。 とりわけ MS-DOS ディスクは、Unix ライクなシステムでサポートされているケース が多く、デフォルトではほんのわずかな属性しかサポートされていません(また これらの属性を定義するのは普通とはいえません)。 その場合、Unix ライクなシステムは標準的な属性をエミュレートします(おそらく 特別なファイルをディスク上に置いて、実装しています)。またそれらの属性は、 普通 mount(1) コマンドで調整できます。

注意すべき重要な点は、ファイルを追加したり、削除したりするのに関係してくる のが、そのファイルのパーミッションを表すビットとそのファイルがあるディレクトリの所有者だけ、という点です。その Unix ライクなシステム が、より高度な手法(POSIX ACL のような)を持っていれば話は別ですが。 システムに他の拡張機能がない場合(Linux 2.2 は普通は持っていません)は パーミッションを表すビットに何もパーミッションが無いファイルは、ディレクトリ に許可があるなら削除できてしまいます。 また、親ディレクトリが子ディレクトリにユーザやグループを変更できるように していると、そのディレクトリ配下のものはすべて、そのユーザとグループに置き換え が可能になります。

セキュリティに関して、IEEE の POSIX 規格では、ACL に関してのきちんとした 技術を定義していて、ユーザやグループが持つパーミッションのリストをサポート しています。 ただ残念なことに、広くサポートされていないだけでなく、Unix ライクなシステム であってもきちんと同じ方法でサポートされていません。 たとえば、普通の Linux 2.2はファイルシステムに ACL はおろか、POSIX ケイパ ビリティの値すら持っていません。

Linux で注目に値するのは、デフォルトでは root ユーザに対して ext2 ファイル システムの領域をほんのわずかしか割り当てない点です。 これは、不完全ではありますがサービス拒否攻撃に対して防御になります。 あるユーザが root ユーザと共有しているディスクを一杯にしたとしても、root ユーザには使い残しでちょっとした領域が残ります(たとえば重要な機能のために とっておけます)。 デフォルトでは、ファイルシステム領域の 5% が確保されています。mke2fs(8) の「-m」オプションをよく見てください。

3.2.2. 作成日時の初期値

作成日時には、下記のルールを適用しています。 Unix システムでは、新しいファイルシステム・オブジェクトが creat(2) や open(2) で作成されると、uid にはそのプロセスの euid が設定され、gid にはそのプロセス の egid が設定されるケースが多くあります。 Linux では fsuid という拡張機能がある分、少々異なっています。 uid にはそのプロセスの fsuid が、gid にはそのプロセスの fsguid が設定されます。 ディレクトリに setgid ビットが立っているか、そのファイルシステムの grpid が 立っていれば、gid はそのディレクトリの gid が実際には設定されます。 ディレクトリに setgid する拡張機能は、Sun Solaris や Linux を含む多くの システムでサポートしています。 先に書きましたが、「プロジェクト」ディレクトリ(ある「プロジェクト」用の ディレクトリ)では、そのプロジェクト用に特別にグループを作成します。 ディレクトリはそのグループが所有者で setgid してあります。そこにファイルを 置くと、自動的にプロジェクトが所有することになります。 同様に、setgid ビットが立っているディレクトリ中に新しいサブディレクトリを 作成すると(ファイルシステムの grpid も設定していない)、新しいサブディレクトリ にもその setgid ビットが設定されます(つまりプロジェクト用のサブディレクトリ にも好都合です)。これ以外のケースでは、setgid は新しく作成したファイルに対して は普通に振る舞います。「ユーザプライベートグループ」という仕組みの理論的な 根拠がここにあります(Red Hat Linux 他で使われています)。 この仕組みにおいては、メンバーそれぞれは自分たちだけで構成している 「プライベート」グループに属していて、デフォルトではそのグループにどのファイル の読み書きも可能としています(グループに属しているのは自分たちだけなので)。 このように、ファイルのグループ構成メンバーが継承されると、読み書きの権限も 継承されるわけです。 【訳註:ユーザプライベートグループについては、この説明だけではわかり難いので、 ユーザプライベートグループ も参照してみてください】 基本的なファイルシステム・オブジェクトのアクセス制御の値(読み書き、実行)は、 (要求された値 & ~ プロセスの umask)から割り出します。 新しいファイルでは、sticky ビットも setuid ビットも常に立っていません。

3.2.3. アクセス制御属性の変更

chmod(2)や fchmod(2)、chmod(1) を使って変更できますが、chown(1)や chgrp(1) も見てください。 Linux では、Linux 独自の属性を chattr(1)で操作できるものもあります。

Linux で注意する点は、root だけしかファイルの所有者を変更できない点です。 Unix ライクなシステムには、一般ユーザでも他のユーザにファイルの所有権を 移動できてしまうものもあります。これは混乱を招くもとなので、Linux では許して いません。 たとえば、ディスク使用量の制限をかけたい場合にそのような操作ができてしまうと、 大きなファイルは他の人(犠牲者)のせいだ、という言い訳を許してしまうことになり ます。

3.2.4. アクセス制御属性を使用する

Linux や他の Unix ライクなシステムの大半では、読み書きの属性値はファイルを オープンした時にだけチェックされます。つまりその後に読み書きしても、再チェック は行われません。 しかし、ファイルシステムは Unix ライクなシステムの根幹なので、システム コールを何度も呼び出すことで、これらの属性をチェックしています。 これらの属性をチェックするシステムコールには、open(2)や creat(2)、link(2)、 unlink(2)、rename(2)、mknod(2)、symlink(2)、socket(2) があります。

3.2.5. ファイルシステムの階層

長年の慣例で、「何のファイルはどこに置く」という約束事があります。 出来るだけきまりを守って、ディレクトリ階層の中に情報を格納してください。 たとえば、全体に関連する設定情報は /etc に置いてください。 Filesystem Hierarchy Standard (FHS)は、この慣例を論理的に定義しようとして おり、Linux システムは広く採用しています。 FHS は従来の Linux Filesystem Structure standard (FSSTND)をアップデート したもので、Linux や BSD、System V から知恵を拝借しています。 http://www.pathname.com/fhs に FHS の情報がありますから、ご覧ください。 概略については Linux では hier(5)を、Solaris では hier(7)を参照してください。 慣例は時には一致しない場合がありますが、コンパイルやインストール時に可能 な限り融通が効くようにしておいてください。

Linux Standard Base が、FHS を 採用したことに触れておきます。この組織は Linux ディストリビューション間の 互換性を高め、準拠した Linux システムならどんなソフトウェアでも動作するように 規格を作り、それを促進する機関です。