UNIX / Linux では、複数のユーザーで同一のマシンを使用することを前提に 設計されています(マルチユーザの概念). そこで, UNIX / Linux においてファイルへのアクセス権制御, 即ち他人に見せてもよいファイル・見せたくないファイルの制御が 重要となります.
UNIX / Linux では, 自分のホームディレクトリへ他人が勝手にファイルを 書いたり, 自分のメールを他人に読まれたりされないようにすることが 可能です. また特定のグループに所属するメンバーのみ読み書きが可能なファイルを 作ることもできます. ここでは, このようなファイルのアクセス権の制御について見ていきます.
自分のホームディレクトリで ls コマンドを幾つかのオプションを指定して 実行すると, およそ以下のような出力が得られます.
$ ls -Flag total 100 drwxr-xr-x 9 inex inex 4096 Oct 13 18:55 ./ drwxrwsr-x 319 root staff 12288 Oct 18 10:47 ../ -rw-r--r-- 1 inex inex 266 May 12 2000 .alias -rw------- 1 inex inex 6169 Jan 15 2003 .bash_history -rw-r--r-- 1 inex inex 174 Mar 16 2001 .bash_logout -rw-r--r-- 1 inex inex 91 May 12 2000 .bash_profile -rw-r--r-- 1 inex inex 55 May 12 2000 .bashrc -rw-r--r-- 1 inex inex 375 May 12 2000 .cshrc -rw-r--r-- 1 inex inex 286 May 12 2000 .emacs -rw-r--r-- 1 inex inex 1077 Oct 19 2001 .kkcrc drwxr-xr-x 2 inex inex 4096 Dec 6 2000 .ncftp/ -rw-r--r-- 1 inex inex 169 Sep 22 2001 .nexrc -rw-r----- 1 inex inex 13 May 12 2000 .qmail -rw-r----- 1 inex inex 120 Oct 21 16:52 .qmail-member drwxr-xr-x 2 inex inex 4096 May 17 2000 .ssh/ -rw-r--r-- 1 inex inex 39 Nov 3 2003 .users -rw-r--r-- 1 inex inex 1919 Sep 8 2001 README drwxr-xr-x 9 inex inex 4096 Sep 3 16:56 bbs/ drwxr-xr-x 2 inex inex 4096 Dec 1 2003 cgi-bin/ drwxr-xr-x 2 inex inex 4096 Sep 3 11:44 lib/ drwxr-xr-x 7 inex inex 4096 Sep 24 15:27 public_html/ drwxr-xr-x 13 inex inex 4096 Sep 10 19:28 rps/ -rw-r--r-- 1 inex epnetfan 363 Jun 20 12:11 sample.txt |
この出力の最下行を例に取って, この読み方を解説します. 左から順に,
-rw-r--r-- | ファイルモード |
1 | ファイルへの"リンク数" |
inex | ファイルの所有者 |
epnetfan | ファイルの属するグループ |
363 | ファイルの大きさ(バイト単位) |
Jun 20 12:11 | ファイルの最終更新時刻 |
sample.txt | ファイルの名前 |
$ man ls |
一番左側の表示の文字列はファイルの「モード」, すなわち ファイルの型 (type) と利用権限 (permission) を表しています. 例えば, sample.txt のすぐ上の rps/ を見ると,
d rwx r-x r-x
左端の1文字はファイルの型を示します. 取りうる文字と型は後述します.
続く文字列で利用権限を示しています. 利用権限の許可対象には,
があり, それぞれに対する許可情報を,
と読んでいます.
また利用権限には,
d rwx r-x r-x ^ ^^^ ^^^ ^^^ | | | | | | | アザーズパーミッション | | | | | グループパーミッション | | | ユーザーパーミッション | ファイルの型(type)
- --- --- --- d rwx rwx rwx l s s t s S S b c P
左端の文字とファイルの型は, 次のように対応づけられています.
- | 通常のファイル |
d | ディレクトリ |
l | シンボリックリンク |
s | ソケット |
b | ブロックデバイス |
c | キャラクタデバイス |
P | 名前つきパイプ |
また, 利用権限は以下の通りです.
- | その権限が出ていない |
r | 読み込み許可 |
w | 書き込み許可 |
x | 実行許可 |
s | s ビットが立っていて, かつ実行許可 |
S | s ビットが立っていて, かつ実行不可 |
t | スティッキー(sticky) |
s ビットについては後述します (スティッキー(sticky)については[付録2]参照).
ファイルの利用権限を設定するには chmod コマンドを用います. 基本的な使い方は次の通りです(詳しくは man chmod).
$ chmod <mode> file1 [file2 ...]
<mode> の部分には 0 から 7 までの数字を 3 桁並べたものが入ります. 左の桁から順にファイルの所有者, ファイルの所属グループ, その他のユーザーに対する利用権限を示します. 各々の読みだし, 書き込み, 実行権限は 4, 2, 1 の数字で表され, 上の <mode> にはこの数字の和が代入されます.
許可 | 記号 | 数字 |
---|---|---|
読込 | r | 4 |
書込 | w | 2 |
実行 | x | 1 |
例えば, モードを -rw-rw-r--
と変えたい場合,
-rw-rw-r-- 42 42 4 | | | 6 6 4 <mode>となるので,
$ chmod 664 fileとすれば変更できます.
上では <mode> を数字で与えましたが, 記号で与えることもできます. <mode> の数字列の代わりに,
対象 | 操作 | 許可 |
---|---|---|
[ugao] | [+-=] | [rwxst] |
対象と操作の文字は以下の意味を表します.
対象 | 操作 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
この場合, 先の例と同じ設定にするには次のようにします.
$ chmod u=rw,g=rw,o=r file
s ビットとは, あるファイルの実行者を「成り変わる」機能のことを言います.
s ビットには, SUID ビットと SGID ビットの二種類あります.
具体例で見て行きましょう. SUID の例として /usr/bin/passwd を見てみます.
第二回目の実習で, passwd コマンドが出てきました. passwd は /usr/bin/ ディレクトリに存在します. passwd コマンドを実行してパスワードを変更すると, /etc/shadow が書き変わるのでしたね. そこで, /etc/shadow のパーミッションを見てみると,
$ ls -l /etc/shadow -rw-r--r-- 1 root root 22485 Oct 21 16:52 /etc/shadow |
ですから, このファイルの書き込みができるのは, このファイルの持ち主, すなわち root だけです. しかし, 誰もがパスワードを変更したい(/etc/shadow が書き変わって欲しい) と思っています. どうやって /etc/shadow を書き変えることができるのでしょうか?
そこで /usr/bin/passwd のパーミッションを見てみます. すると,
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 24680 Apr 8 2002 /usr/bin/passwd |
左から 4 番目に s という文字が書かれています. これが SUID ビットで, このファイルが実行されると, プログラムの持ち主がこのファイルを実行したものと解釈されることを表します. つまり, passwd コマンドを実行すると, root が実行したものと解釈される のですから, /etc/shadow を書き換えることができるという訳です.
SGID は上のグループ版です. 似たようなものなので説明は割愛します.
では, 実際にファイルを作ってみてパーミッションの変更等をしてみましょう.
以下の作業では, login, logout を繰り返すのが面倒なのでちょっとおまじないをします. まず, もう一つ kterm を立ち上げ, 今 login しているアカウント(foo さん)の 相方(bar さん)になりかわります.
$ kterm & |
< kterm をもう一つ立ち上げる. |
新しく立ち上げた kterm を用いて以下のコマンドを打ち込んでみてください.
$ whoami foo $ su bar Password: $ whoami bar $ cd |
< 現在のログインアカウント名を尋ねる(foo だったとする). < bar になりかわる. このとき bar さんのパスワード入力が必要. < 無事 bar さんになっているか現在のアカウント名を尋ねる. < bar さんのホームディレクトリに移動しておく. |
以下, もともとあった kterm を "A ターミナル", あたらしく起動し bar さんになり変わった状態の kterm を "B ターミナル" と呼ぶことにします.
では, まず A,B 両ターミナルで以下の作業をして ディレクトリとファイルを作成してください.
$ cd $ mkdir secret $ echo 'secret-word' > ./secret/word.txt $ chmod ??? secret $ chmod ??? secret/word.txt |
< ホームディレクトリに移動. < secret ディレクトリを作成. < 'secret-word' 部分は好きな単語に置き換える. secret ディレクトリの中に ファイルを作成. < chmod をつかって secret ディレクトリのパーミッションを変える. ファイルが相方から見えないように ??? の部分を考えよう. < chmod をつかって secret/word.txt ファイルのパーミッションを変える. 上と同様にファイルが相方から見えないよう ??? の部分を考える. |
foo さん, bar さん共に, 今作った相手のファイルを見てみましょう.
$ cat ~foo/secret/word.txt |
$ cat ~bar/secret/word.txt |
お互いに相手のファイルが見えなければ成功です. もし見られてしまった場合は, 先の chmod コマンドを 先程とは違うモードで再度実行し, 見られない様にしてください.
見られないようにする方法がわかったら, 今度はいろいろな モードにしてその違いを確かめてください. ディレクトリのモードを変えると, そのディレクトリに移動できなくなったり するはずです. cd コマンドなどを試してみてください.
最後に自分の作った word.txt を消去してください. このとき, どのようなモードだとファイル消去できないかも是非試してください.
この知識は自分の卒論などを誤って消してしまわないためにも重要です! つまり, 消去できないようにファイルのモードを変更しておけば, 誤って rm コマンドを実行しそうになったときも, 消去されずに済むわけです!
UNIX / Linux ではファイルモードの設定によって, 他人のファイルを見る ことが可能です. 大抵の場合, 普通に作成したファイルは他人が見れる状態にあるでしょう. もし, 本当に見られては困る内容のファイルはモードを正しい設定にするように 心がけましょう. 他人がみても良い設定のファイルは基本的に "見ても良い" 訳ですが, "mail" といった文字列のつく名前のファイルやディレクトリの中, あるいは個人的な情報であることが推測できるファイルは, 仮に見れる状態にあっても絶対に見てはいけません. また, 同様に見られては困るファイルを見れる状態で置いておくことも 避けましょう. こういったファイルは, 見た方も見られた方も嫌な思いをしてしまいます.
リンクとは, あるファイルやディレクトリを, 別のファイルやディレクトリに関連付ける仕組みをいいます.
リンクには,
先に ls コマンドを用いた説明で, その実行結果の左から2番目に表示される数字は, リンク数を表すと述べました.
$ ls -l sample.txt -rw-r--r-- 1 inex epnetfan 363 Jun 20 12:11 sample.txt |
これは正しくは「ハードリンク」の数を表しています. ハードリンクの数は, 簡単に言うとファイルの「名前」の数を表しています.
人間は文字列(上の場合 'sample.txt')でファイルを識別しますが, システムはファイルを「番号」として管理しています. UNIX では, この番号を「i-ノード」と呼びます. ファイルと i-ノード番号は1対1に対応(リンク)しています.
i-ノードという概念は, そもそも UNIX のカーネルが, それぞれのパーティションに, 装置番号(device number)を割り当て, 「ディスク」ではなく「ファイルシステム」 という論理的なレベルで処理を行うことに由来しています. ファイルシステムは, 論理的なブロックの集まりから構成され, 単位となるブロックの大きさはシステムによって異なります.
ファイルシステムは, 次のような4つの部分に分けられます.
i-ノードには, 次のような情報が含まれています. ここで注意して欲しいことは, i-ノードにはファイル名は含まれていないということです.
ls -i
とするとファイルの i-ノード番号を実際に見ることができます.
$ ls -i sample.txt 31657 sample.txt |
ハードリンクの数は, 実はそのファイルの対応している i-ノード番号を 参照しているファイルの数を表しています.
したがって同じ i-ノード番号をもつ別名のファイルを作ること, 即ちファイルに複数の名前をつけることができます. これは "ln" コマンドで実行できます.
touch コマンドで空のファイル file1 を作り試してみましょう. 通常ファイルのリンク数は1です.
$ touch file1 $ ls -l file1 -rw-r--r-- 1 inex epnetfan 0 Jun 27 02:39 file1 |
$ ln file1 file2とすると file1 に新しい名前 file2 を加える(リンクを張る)ことができます.
$ ls -l file1 file2 -rw-r--r-- 2 inex epnetfan 0 Jun 27 02:39 file1 -rw-r--r-- 2 inex epnetfan 0 Jun 27 02:39 file2 |
リンク数が2に増えています. 一方ディレクトリのリンク数は必ず2以上になります. リンクを消すには rm コマンドを使います.
上の ln コマンドにオプション -s をつけて実行してみます. これは「シンボリックリンク」と呼ばれ, 簡単にいうとファイルの「別名」をつけるようなものです. 類似のものに, Windows では「ショートカット」, Mac では「エイリアス」があります.
$ ln -s file1 file3 $ ls -l file1 file3 -rw-r--r-- 2 inex epnetfan 0 Jun 27 02:39 file1 lrwxrwxrwx 1 inex epnetfan 5 Jun 27 02:45 file3 -> file1 |
ハードリンクの場合は i-ノードを直接参照しているのに対し, シンボリックリンクは「ファイル名」を参照しています. 従って、上の例でも file1 のリンク数も増えませんし, file3 のリンク数も1のままです.
シンボリックリンクの特徴をみるため, 次のようにコマンドを実行してみましょう.
$ rm file1 $ cat file3 cat: file3: No such file or directory |
$ ls file3 file3 |
これはシンボリックリンクでは「ファイル名」を参照しているためです. 参照先のファイル名が消去されてしまうと, 参照していたファイルの i-ノードを見ることができなくなり, 上の例では file3 を表示しようとするとエラーが返るのです.
ハードリンクとは異なり, ディレクトリに対するシンボリックリンクは可能です. シンボリックリンクを消すにはやはり rm コマンドを使います.
スティッキービットとは, ファイルまたはディレクトリの所有者だけが目的のファイルの削除や名前の変更を行えるようにする機能のことです.
s ビットの時と同様に具体例で見て行きましょう. ルートディレクトリ( / )の下には tmp というディレクトリがあります. このディレクトリのパーミッションを見ると,
$ ls -l / drwxrwxrwt 6 root root 1024 Jul 1 12:16 tmp |
これによるとこのディレクトリは誰でも読み書きができるようになって いますが, 「アザーズ」の実行許可のところに t と書かれています.
これがスティッキービットで, それによって, このディレクトリの中にあるファイルの消去や名前の変更は, そのファイルの所有者だけが行えるようになるということになります.
ls -l /dev
としてみると以下のような出力が得られます.
$ ls -l /dev/ total 50 -rwxr-xr-x 1 root root 14373 Nov 30 1996 MAKEDEV* -rwxr-xr-x 1 root root 28676 Nov 30 1996 MAKEDEV-C* -rw-r--r-- 1 root root 1035 Nov 30 1996 README.MAKEDEV -rw-r--r-- 1 root root 1434 Nov 30 1996 README.MAKEDEV-C lrwxrwxrwx 1 root root 4 Jan 15 21:46 X0R -> null crw-r--r-- 1 root root 10, 134 Jun 8 1996 apm_bios crw------- 1 root root 16, 1 Feb 19 1994 arp crw-rw-rw- 1 root sys 10, 3 Jul 18 1994 atibm crw-rw-rw- 1 root sys 14, 4 Jul 19 1994 audio crw-rw-rw- 1 root sys 14, 20 Jul 19 1994 audio1 brw-r----- 1 root disk 29, 0 Feb 16 1995 aztcd crw-r--r-- 1 root root 10, 128 May 25 1996 beep . . . crw-r----- 1 root disk 27, 25 Dec 8 1995 zqft1 crw-r----- 1 root disk 27, 26 Dec 8 1995 zqft2 crw-r----- 1 root disk 27, 27 Dec 8 1995 zqft3 |
ファイルモードを見ると, 一番左が見慣れない c や b になっています. このようなファイルは通常のファイルではありません.
UNIX では基本的にあらゆる物を抽象化して「ファイル」として扱います. たとえばマウス(/dev/mouse) や画面等もファイルに抽象化して取り扱ってしまいます.
このようなファイルは「デバイスファイル(device file)」と呼ばれます. デバイスファイルには, c で表されるキャラクタデバイスと, b で表されるブロックデバイスがあります.
★ /dev/null ★次を実行してみましょう.
$ ls > /dev/null何も出力されません. では, これはどうでしょう?
$ cat /dev/nullやはり何も表示されません.
/dev/null というファイルは, いかなる入力も捨ててしまう性質を持つデバイスファイルです. コマンドの出力がうるさい時などに, リダイレクトと組み合わせて使います.
※リダイレクトについては次回, 最低限 UNIX / Linux [III]で説明します.最終更新日: 2005/10/22(森川靖大) | Copyright © 2005 inex |