はうすてんぼぶ

コードかいてて疑問に思ったことや、興味あることをつらつらと暇なときに書く場所、ここはそんな場所

ファイルパーミッション

はじめに

ファイルのパーミッションはだいたい何なのかは知っているが、chmodコマンドぐらいしか満足に使い方をしらないので勉強するよ!

パーミッション

UNIXはファイルに対するアクセス許可状態を、オーナ、グループ、その他の3つの単位で設定することができる。

それぞれの単位ごとに、読み出し(read)、書き込み(write)、実行(executable)を可能/不可能にするファイル属性をパーミッションという。

最終的に一つのファイルのパーミッション設定は、rwxrwxrwxのように9文字で表され、左から3文字ずつオーナグループその他のアクセス許可状態を指している。

文字が書かれている場所は可能、「-」が置かれている場所は不可能を指す。

試しに作ってみた例を以下に示す。

% echo "Hello World" > file1
% ls -l file1
-rw-rw-r-- 1 bob bob 12  919 08:37 file1

左側にある「-rw-rw-r--」の箇所がパーミッションに当たる。
今回の場合だと、オーナは、「read/write」、グループは「read/write」、その他は「read」が許可されていることがわかる。

じゃあ一番左の「-」は何なのかというと、これはファイルの種類を指す。
全7種類ありみたいだけれども、上の3つぐらいしか見たことがない。

記号 種類
- 通常ファイル
d ディレクトリ(directory)
l シンボリックリンク(link)
b ブロックデバイス(block device)
c キャラクタデバイス(character device)
p パイプ(pipe)
s ソケット(socket)

/devになら揃ってそう、と思ってls -lしてみた結果を一部載せる。

% ls -l /dev/
brw-rw----+ 1 root cdrom    11,   0  918 03:16 sr0
crw-rw----  1 root video    29,   0  918 03:16 fb0
srw-rw-rw-  1 root root           0  918 03:16 log

sr0はCD/DVDドライブ、fb0はメインディスプレイを指す。
logは名前の通りログファイルなんだろうけどそもそも読むことができなかった。そもそもファイル状態がソケット…とは?

あとsr0のパーミッションの一番右に「+」が付いているが、これは拡張アクセス権限とのこと。
acl(アクセス制御リスト、Access Control Lists)と呼ばれる。
それまで所有者以外のアクセス設定はグループ単位 or 全員みたいに極端なことしかできなかったが、aclを扱うことで、ユーザを個別に設定してアクセス許可/不可の設定ができる、とのこと。
BK class: ls -lで表示されるモードの11桁目を参考にしました。

新規作成時のパーミッション値の設定:umask

umaskコマンドで、パーミッションマスク値の設定ができる。
このパーミッションマスク値を設定すると、新規にファイルやディレクトリを作った時のパーミッションに影響を与える。

とりあえず、一般ユーザとrootで試してみた。

% echo "test1" > file 
% ls -l file
-rw-rw-r-- 1 bob bob 5  919 09:14 file

% umask
002

% sudo -i
# cd /home/bob
# echo "test2" > root_file

# ls -l root_file
-rw-r--r-- 1 root    root    6  919 09:20 root_file

# umask
022

一般ユーザのときは002、スーパーユーザのときは022なことが分かった。

ファイルやディレクトリの新規作成時のパーミッション処理は、仮パーミッション値とマスクの否定値をアンド計算したものになる。
パーミッション値は、ファイルだと666、ディレクトリだと777になる。

上の例で、一般ユーザがファイルを作るときは、
110110110 & ~000000010、となり、

  110110110
&111111101
ーーーーーーー
110110100 > 664 > rw-rw-r-- となる。

umaskコマンドに新しいパーミッション値を引数として与えるとマスク値が変更される。

% echo "umask 002" > file_a
% umask 077
% echo "umask 077" > file_b
% ls -l file_a file_b
-rw-rw-r-- 1 bob bob 10  919 09:33 file_a
-rw------- 1 bob bob 10  919 09:33 file_b

今使っているシェル内でだけ変更は有効になるので、永続的に変更したいのであれば.zshrcなどのシェルの設定ファイルに書くと良いのかも。

パーミッションの変更:chmod

マスクは新規にファイルを作る時に用いられるが、既に作成済みのファイルのパーミッションを変更したい場合はchmodコマンドを使う。

chmodの主な使い方は2種類で、+-=でモードの追加・削除・設定をするモード文字での設定方法(設定モード)と、直接パーミッション値を8進数3桁で設定する方法(8進数モード)がある。

語源は、CHange MODより。

設定モード

まず例から、

% chmod [MODE] [FILE]
% chmod u+rwx file1 (1)
% chmod go-r file2 (2)
% chmod o=rw file3 (3)

それぞれのchmodとファイル名の間にある[MODE]の部分を変えて、パーミッションを変更する。

(1)の例を使うと、「u+rwx」の部分は、
どのユーザ」の「どの権限」を「どうするか」の3つを示している。
この例だと、オーナ読込・書込・実行権限追加する、といった意味になる。


どのユーザ」には、以下の4種類の英字が入る。

u オーナ
g グループ
o その他ユーザ
a 全ユーザ(省略可)

(2)の例のように、複数入れても問題ない。a+何かで、対象が重複して入れても問題ない(aが優先されるだけなので)。
また、省略した場合は、自動的に全ユーザが対象になる。


どうするかオペレータと呼ぶらしい)」は、以下の3種類の記号が入る。

+ モード追加
- モード削除
= モード設定

これは1つのみ設定可能。省略もしてはいけない。
あと、削除する場合に、対象のユーザがその権限を持っていなくても特にエラーはでない(設定に寄る?)。

どの権限モードと呼ぶらしい)」は、以下の5種類の英字を入れる。

r 読込
w 書込
x 実行
s SUIDビット・SGIDビット
t stickyビット

これも例(1)(3)のように一度に複数入れることが可能。
下の2つのsとtについては後述する。

パーミッション値を使う

パーミッション値を使うほうが自分はしっくりくる。
使い方はシンプルで以下のようになる。

% chmod [OCTAL_MODE] [FILE]
% chmod 664 file1 (a)
% chmod 700 file1 (b)
% chmod 777 file1 (c)

[OCATAL_MODE]の箇所に8進数の3桁の数値を入れるのみ。
3桁の数値に関しては、マスクのところでも触れたので割愛する。

例にだけ触れとくと、
(a)は、オーナとグループに読込・書込を許可し、その他のユーザに読込を許可。
(b)は、オーナにのみ読込・書込・実行を許可。他のユーザは読込すら許可しない。
(c)は、全ユーザに全権限を与える。

(a)(b)(c)の後にls -lしてみた結果を示す。

% chmod 664 file1
% ls -l file1
-rw-rw-r-- 1 bob bob 12  919 08:37 file1

% chmod 700 file1
% ls -l file1
-rwx------ 1 bob bob 12  919 08:37 file1

% chmod 777 file1
% ls -l file1
-rwxrwxrwx 1 bob bob 12  919 08:37 file1

ファイルモードを知る

chmodコマンドから急に、モードという単語が出てきた。

UNIXは、パーミッションを9ビット、さらに3つの属性を追加した12ビットセットをファイルモードとして管理している。
このファイルモードから来ている。

パーミッションの9ビットは言わずもがな、rwxrwxrwxの許可/不許可を指すそれである。

先に12ビットセットがどう並んでいるかだけ示す。

[SUID][SGID][stcky]rwxrwxrwx

パーミッション9ビットの前に3ビット分、SUID、SGID、sticky用のビットが付いている状態。
この3属性について説明していく。

SUID (Set User ID) ビット

一般ユーザがファイルを実行すると、普通はそのコマンドを入力したユーザIDが、プロセスのユーザIDになる。
SUIDビットを設定(1に)しておくと、誰が実行しようともファイル所有者(オーナ)のユーザIDが、そのプロセスの実行ユーザIDとみなされる。

こうしておくことで、「ファイル所有者が実行しないと正常に処理されない」ようなプログラムも、他のユーザが実行した場合でも正常に動かすことが可能になる、とのこと。

SGID (Set Group ID) ビット

このファイルのグループIDが、実行プロセスのグループIDになる。
いわゆるSUIDのグループ版。

stickyビット

この値が1になっていると(chmodで+t)されていると、ファイル所有者とスーパユーザだけが書き込み権限を持つようになる。
主にディレクトリに対してこの設定をするようで、/tmpディレクトリのように、多くのユーザに共有されるがディレクトリの削除は困る、といった場合に付けるらしい。

実行可能ファイルに対してstickyビットがセットされている場合には、実行終了後もメモリ開放しない(スワップ領域の保存)という扱いになるため、次回の起動が早くなるらしい。

ここらへんはもう少し触ってみないとわからなさそう。

自分の状況を把握:id, groups

パーミッションの設定をする際は、idコマンドやgroupsコマンドで自分の所属を知っておくことも重要。

groupsコマンドは、自分の所属するグループ名を一覧で表示。
idコマンドは、ユーザID,グループID,所属するグループIDを表示してくれる。

% groups
bob adm dialout cdrom plugdev lpadmin admin sambashare

% id
uid=1000(bob) gid=1000(bob) groups=1000(bob),4(adm),20(dialout),24(cdrom),46(plugdev),116(lpadmin),118(admin),124(sambashare)

あまり設定したつもりがなくても結構勝手にgroupに入っていたので驚いた。

おわりに

これでパーミッションに関する箇所は網羅したのではないかなぁ。
stickyビットがまだあいまいなので要復習。

参考資料

Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本, Chapter 9 ファイルのアクセス制御, p138-p148.