ls に -l フラグを付けると、ファイルのパーミッションを調べることができる。 たとえばこんな風に表示される。
-rw-r--r-- 1 north web 1302 Nov 30 14:31 index.html
パーミッションを表わしているのは、最初の「-rw-r--r--」の部分だ。
最初の1文字目の「-」は、ファイルのタイプを示している。 ファイルが普通のファイルなら「-」だし、ディレクトリならば「d」になる。 これはパーミッションとは関係がない。
次の3文字が、ファイルの所有者のパーミッションを表わしている。 「rw-」がそうだ。 ここでは、所有者 north は読み出し可、書き込み可、実行不可であることが分かる。 次の3文字「r--」はグループに対する許可を表わす。 ここでは web というグループに対して、読み出し可、書き込み不可、実行不可であることが分かる。 最後の3文字「r--」は所有者でも同一グループでもないユーザすべてに対するパーミッションで、読み出し可、書き込み不可、実行不可であることを示している。 たとえば north というユーザならば、このファイルを自由に編集することができるが、他のユーザは読み出すだけで、変更したり消したりすることはできない。 パーミッションに違反すると、次のようなエラーメッセージに出くわすことになる。
index.html: Permission denied.
関係ないけど、denied は「デニエド」じゃなくて「ディナイド」と読む。
一般のファイルの場合は、読み出しと書き込みのいずれかの許可が付いているが、実行可能なプログラムの場合は、実行許可を表わすパーミッションが付いている。 たとえばこんな風になっているはずだ。
-rwxr-x--- 1 north web 43710 Oct 18 04:34 bb.sqq.cgi
この場合は、所有者 north は読み出し、書き込み、実行のすべてが可能、グループ web は読み出しと実行が可能、その他のユーザはいっさい不可ということになる。
パーミッションはディレクトリにもついている。 ディレクトリのパーミッションも見てみよう。
drwxrwxr-x 1 north web 512 Apr 7 02:20 public_html
ディレクトリの場合は、パーミッションフラグの意味が若干異なってくる。 r はディレクトリで ls を実行しファイルのリストを得られるか否か、 w はディレクトリに新規にファイルを作ることができるか否か、 x はディレクトリに cd で移動できるか否かを示す。 上記の例の場合、所有者とグループ web に属するユーザはディレクトリを自由にすることができるが、他の一般ユーザは新規にファイルを作れないことを意味する。
以上をまとめて表にしておこう。
フラグ ファイル ディレクトリ r 読み出し可能 ls 実行可能 w 書き込み可能 ファイル作成可能 x 実行可能 cd 可能
なお、root はパーミッションとは無関係になんでもできる。
パーミッションを変更するには、chmod というコマンドを使う。 パーミッションを変更できるのは、そのファイルの所有者と root だけだ。
chmod は2種類のインターフェースを用意している。 1つめが、記号を使ってフラグをセットしたりリセットしたりするスタイルだ。 たとえば、ファイルの実行許可をオンにしたいときは +x を指定する。
% ls -l foo.sh -rw-r--r-- 1 north web 350 Nov 30 14:31 foo.sh % chmod +x foo.sh % ls -l foo.sh -rwxr-xr-x 1 north web 350 Apr 7 01:35 foo.sh
所有者だけに許可を与えたいなら、「u+x」のように指定する。 u というのが所有者を意味する修飾子、+ がオンにするというコマンド、x が実行許可を意味している。 逆にオフにしたいなら「g-x」のようにする。 これはグループに対して実行許可をオフにすることを意味する。 指定は、複数のグループやフラグに対して同時に行うことができる。 「go-wrx」とすれば、所有者以外には読み書き実行全部不可ということになる。
目的 オプション 意味 誰に対して? u 所有者 (user) g グループ (group) o その他 (other) どうする? + オンに変更 - オフに変更 どのフラグ? r 読み出し (read) w 書き込み (write) x 実行 (execute)
2つめの方法が、パーミッションを数字で指定する方法である。 「rwxr-x---」というパーミッションを与えたいとき、オンの部分を1、オフの部分を0とする。 すると「111101000」となる。 これを8進数に変換すると「750」になる。 chmod はこれを直接パーミッションとしてファイルに割り当ててくれるのだ。
% ls -l foo.sh -rw-r--r-- 1 north web 350 Nov 30 14:31 foo.sh % chmod 750 foo.sh % ls -l foo.sh -rwxr-x--- 1 north web 350 Apr 7 01:35 foo.sh
どうして8進数なのかというと、2進数で3ケタがちょうど8進数で1ケタだからだ。
もしかしたら「1755」ってセットするとファイルがディレクトリになるかも! と思うかもしれないが、それはハズレである。 ディレクトリか否かの区別はパーミッションとは無関係だし、「1755」は別の意味を表わすフラグなのだ。 詳しいことは chmod の manpage を見てほしい。
chmod の便利なオプションとして、もうひとつ -R を紹介しておく。 これはディレクトリを指定したときに、そのサブディレクトリを走査してすべてのファイルを変更してくれる。
ファイルにしてもディレクトリにしても、ファイルサイズや変更された日付といった情報の他に、所有者とグループという情報を持っている。 所有者とグループは、ファイルを作成したユーザのそれにセットされる。 正確には、ファイルの所有者は、そのファイルを生成したプロセスの uid と同じにセットされる。 たとえばユーザ north がエディタ(vi とか)を起動すると、vi のプロセスは north と同じ uid を持つことになる。 そして vi がセーブするファイルには、そのプロセスと同じ uid 、すなわち north というユーザの uid が付けられるのである。 他にも、root 権限で動作しているプログラムがログファイルを生成したとすると、そのファイルの所有者は root ということになる。
プログラムが、特に理由もないのに動かなかったり、動作がおかしかったりするとき、まずパーミッションを疑ってみるのがよい。 アプリケーションによっては、指定された uid でないと正しく動作しないものもあるし、 特定の uid で動作するよう特殊な仕掛けを施されているものもある。 そういう場合に、「Permission denied」で落ちていることもあるのだ。
ゲームでは、ハイスコアを記録する機能がつきものだ。 しかしハイスコアのリストをファイルとしてセーブしておくと、不埒なユーザがそれを勝手に書き換えて、トップを取ったように見せかけるかもしれない。 これを防ごうとして、ハイスコア・ファイルのパーミッションを一般ユーザには書けないモードにセットしたりすると、不正をしないユーザがゲームで本当にハイスコアを出したときに困ったことになる。 というのも、ゲームプログラムはユーザによって起動されているから、ハイスコア・ファイルを変更しようがないのである。
こういうときに役立つ仕組みが setuid だ。 「setuid された」プログラムを実行すると、そのプロセスの中では誰でも、そのプログラムの所有者と同じ特権を得ることができるのである。 ゲームプログラムを setuid しておけば、プレイヤーはゲームプログラムと同じ特権を(ゲームしている間だけ)得ることができる。 ハイスコア・ファイルも変更することができ、問題を解決できるというわけだ。
もちろん、setuid という仕組みはゲームのために作られたわけではない。 たとえばパスワードを変更するときは、/etc/passwd を変更する特権が一時的に必要になる。 もちろんそれが可能なのは root だけだが、それをいちいち root に頼むわけにはいかない。 passwd コマンドのパーミッションを見てみよう。
% ls -l /usr/bin/passwd -r-sr-xr-x 2 root wheel 24976 Feb 15 19:44 /usr/bin/passwd
所有者の実行許可が、x ではなく s になっている。 これが setuid ビットだ。 passwd の所有者は root だから、passwd を実行するユーザは誰でも root と同じ特権を持つことができる(/etc/passwd を変更できる)というわけだ。
setuid 以外にも、ファイルのグループと同じ特権が得られる setgid という仕組みもある。 こちらの場合は、グループのパーミッションの x が s に変わっている (たとえば /usr/bin/lpr などがそうだ)。
setuid はディレクトリに対しても適用できる。 setuid をセットされたディレクトリでファイルを作ると、 そのファイルはファイルを作ったユーザではなく、ディレクトリの所有者と同じ uid が振られる。
このように setuid は便利な機能なのだが、一方で重大なセキュリティ問題を引き起こす危険もはらんでいる。 プログラムを注意深く書かないと、許可したいこと以上の特権を誰にでも与えてしまうような事故につながってしまうのだ。 たとえば FreeBSD では、シェルスクリプトでは setuid できないようになっている (裏をかく方法があるはずだが、調べたことがないので分からない)。
(とりあえず終わり)