パーミッションの管理
Definition 1 パーミッション
- パーミッションとは,ファイルやディクトリに対して持つユーザーやグループの権利を管理する仕組みのこと
- READ(4), WRITE(2), EXECUTE(1) の3つの属性を指定することができる
- 各ファイルやディレクトリのパーミッション内容の確認は
ls -lで可能
Linux環境では複数のユーザーで利用することが前提となっています.このようなシステム設計思想をマルチユーザーといいます. 複数のユーザーが一つのコンピューター上に存在し得る以上,どのユーザーがどのディレクトリ, ファイルに対して所有権やアクセス権を有しているのか?定義する必要があります. この「(ユーザー, ファイル)ごとのアクセス権の管理」という概念がPermissionで,Linuxでは許可されたユーザーのみがファイルにアクセスできる「アクセス制御」が実装されています.
Example 1 (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2とパーミッション)
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 は実行バイナルファイル(ELF)をメモリにロードし,必要な共有ライブラリを解決してからプログラムを起動する 動的リンカプログラムです.これはOSの核となるプログラムなので,システムのとあるユーザーがうっかり削除してしまうとかはあってはならないです.つまり,
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2: 所有者以外は編集できない but 実行できるようにする
というアクセス制御が必要になります.適切なパーミッション設定がマルチユーザーシステムの安全性・安定性に必要であることがわかります.
アクセス権の種類
| 種類 | 意味 | ファイルの場合 | ディレクトリの場合 |
|---|---|---|---|
| r | Readable(4) | ファイルの内容を読むことができる | ディレクトリの内容を一覧表示できる(ls が使える) |
| w | Writable(2) | ファイルを編集・上書きできる | ディレクトリ内のファイルやディレクトリを作成・削除できる(touch, rm, mkdir などが可能) |
| x | eXecutable(1) | 実行ファイルとして実行できる | ディレクトリに移動できる・中にアクセスできる(cd やパス指定が可能) |
| - | 不許可 | 読み・書き・実行のいずれも不可 | 一覧表示・作成削除・移動のいずれも不可 |
グループとパーミッション
Linuxでは,「グループ」というカテゴリでPermissionを管理することができます.このグループとは「ユーザーの集合」のことです. Linuxではユーザー作成時に,ユーザー名と同名の新しいグループが作られ,それが新規作成したユーザーに割り当てられます. ユーザー名と同じ名前のグループが設定される管理方式をユーザープライベートグループ(UPG)と呼びます.
一つのLinuxコンピューターにユーザーが100人とかいるケースでは,1人づつリソース管理するよりもグループ単位で管理したほうが簡単なケースは多々あります.
Example 2 (グループ単位での権限管理のメリット)
会社で一つのLinuxサーバーを共有している時,
- 管理職グループには売上帳票関連ディレクトリのアクセス権を付与
- それ以外のユーザーにはアクセスを禁じたい
というルールを実現したいとします.
この時,一人ひとりのユーザーにディレクトリのアクセス権を設定すると,管理職人数のオーダーで設定工数が発生します. 一方,一旦管理職グループを定義して管理職グループのみにディレクトリのアクセス権を付与するという形にすると工数のオーダーが \(\mathcal{O}(1)\) になります
sudo chgrp -R 管理職グループ <directory-path>
sudo chmod 770 -R <directory-path>-R オプションは,指定したディレクトリ以下すべてのファイルの設定を一度に変更するオプションです.-R を付与しないと,ディレクトリのアクセス権を変更しても, ディレクトリ内のアクセス権は変更されません.
昔のUNIXではユーザー作成時のとき,各ユーザーは users という共通グループが割り当てられる仕組みでした. ユーザー数が少なく,コンピューターを共同作業の場として利用する状況では,この方式でも良いですが,
- 共有は「明示的に」グループを作って行う
という方針へ変更する場合,UPGのほうが安心してシステムを運用できます.つまり,明示的に共有設定をしない限り,他のユーザーからはアクセスできない(=ゼロトラスト運用).
パーミッションの変更
ファイルやディレクトリを作成すると,作成したユーザーがその所有者となります.また,所有グループは,その作成したユーザーが所属するプライマリーグループが所有グループとなります.
$ touch index.qmd
$ ls -l ./index.qmd
-rw-r--r-- 1 ryo ryo 428 Jan 13 14:38 ./index.qmdこのアクセス権を変更するには chmod コマンドを用います.
Definition 2 chmod
ファイルやディレクトリのパーミッションはrootと対象オブジェクトに対して所有権を持っているユーザーとrootユーザーがPermission設定・変更が可能
chmod [option] access-mode fileユーザーのカテゴリ
| 対象 | 説明 |
|---|---|
u |
所有者 |
g |
所有グループ |
o |
その他のユーザー |
a |
すべてのユーザー |
設定の種類
| 対象 | 説明 |
|---|---|
+ |
権限の追加 |
- |
権限の削除 |
= |
権限の指定 |
Example 3 (chmod コマンドの実行例)
# sampleファイルの所有グループとその他ユーザーに書き込み権を追加
$ chmod uo+w sample
# sampleファイルへのその他ユーザーの書き込み権を削除
$ chmod o-w sample所有者と所有グループの変更
すべてのファ入りやディレクトリには,所有者と所有グループが設定されています.所有者と所有グループの変更するには
chown: 所有者の変更chgrp: 所有グループの変更
コマンドを用います.基本的には,変更できるのは root ユーザーのみです.
Definition 3 chown コマンド
- 指定されたファイルやディレクトの所有者とグループを変更する
- グループも合わせて変更する場合はグループ名の前に
.または:を指定する - このコマンドを実行できるのは
rootユーザーのみ
chown [option] user-name[:group-name] file-name変更前と変更後の所有者に対する権限が必要なので,所有者を変更できるのは rootユーザーのみになります. 一方,chgrp は,root 以外に変更前と変更後の両方に属しているユーザーであれば変更できます.
Example 4 (ファイルの所有者とグループを一括でまとめて変更する)
# コロンを用いる
chown user:group file-name
# ピリオドを用いる
chown user.group file-nameDefinition 4 chgrp コマンド
- ファイルの所有グループ(グループ名)を変更するコマンド
root以外に変更前と変更後の両方に属しているユーザーであれば変更できる
chgrp [option] group-name file-nameデフォルトのアクセス権の設定
Definition 5 umask
- 新しいファイルやディレクトリを作成する際に,デフォルトで付与しないパーミッションを指定するもの
- 「マスク」 = 「隠すもの」の意味
- 新規ファイル作成時に,umaskで指定したビットがオフになる(=権限が削除される)
openやmkdirなどのシステムコールで使用される
ファイルを作成すると
$ touch index.qmd
$ ls -l ./index.qmd
-rw-r--r-- 1 ryo ryo 428 Jan 13 14:38 ./index.qmdのようにパーミッション値が定まりますが,この値は umask の値から定まります.umask の値はbashだと
$ umask
0022zshだと
% umask
022です.表示形式が3桁 or 4桁の違いはありますが本質的には同じ設定です.この値を用いてデフォルトのアクセス権は以下のように定まります
- デイレクトリの場合は
777 - umask value - ファイルの場合は
666 - umask value
Example 5 (計算例1)
デフォルトのumask値は 022(8進数)の場合:
ファイル作成時の要求: 0666 (rw-rw-rw-)
umask: 0022 (----w--w-)
─────────────────────────────────────
実際のパーミッション: 0644 (rw-r--r--)
計算式: 0666 & ~0022 = 0644Example 6 (計算例2)
ファイル作成時に
rw-------がデフォルトとなるようなumaskの設定値の例は
# pattern 1
umask 0067
# pattern 2
umask 0066となります.他にも 0166 とかもありえます.
umaskの値の変更を行いたいときは,どのログインシェルを用いるかによって変わりますが,基本的には
| 設定場所 | GUI | SSH |
|---|---|---|
| ~/.zprofile | ❌ | ✅ |
| ~/.profile | ❌ | ✅ |
となります.CLI操作が基本の場合はbash, zshそれぞれに対応した設定ファイルを変更すればよいですが,GUIの場合は少し厄介です. なおumaskの値は,親プロセスから子プロセスに引き継がれます.
特殊なパーミッション
特殊なパーミッションとして
- SUID(Set User ID)
- SGID(Set Group ID)
- スティッキービット
があります.
SUID
Definition 6 SUID
- 一時的にファイルの実行権限を別のUIDのユーザに変更できる機能のこと
- SUIDが付与されたファイルは実行時にそのファイルの所有者の権限で実行される
- Linuxのファイルシステム上では,ディレクトリに対して設定しても効果はない(see SUID has no effect on directories with Linux)
プロセスには実ユーザーID(real user ID)と実効ユーザーID(effective user ID)が設定されています.
- 実ユーザーID(real user ID): プロセスを起動したユーザー(=プロセスの所有者)
- 実効ユーザーID(effective user ID): プロセスが実行されるときの権限を持つユーザー
SUIDを設定することで,実ユーザーが一般ユーザーでも実効ユーザーIDがroot権限を持つなどの設定が可能になります.
SUIDの活用例
「セキュリティ的に一般ユーザーの書き込み権限などは絞っておきたいが,利便性を考えると root ユーザーでなくても更新させたい」というファイルがあるとき, SUID をうまく使うことで用途を限定した上で,セキュアなファイルの実効を一般ユーザーにも許可できるというメリットがあります.
SUIDの使用例として,passwdコマンドがあります.Linuxではパスワードのデータを/etc/shadowで管理しています.
$ ls -l /etc/shadow
-rw-r----- 1 root shadow 9812 Jul 15 19:03 /etc/shadowPermissionを確認すると,root以外は読み取れない(= 暗号化パスワード解読を防ぐため)設定になっています.パスワードを変更するときは passwd を用いますが, 一般ユーザーでも自分自身のパスワードは sudo なしで実行できます.ではどうやって /etc/shadow に書き込んでいるかというとSUIDが設定されているからが答えになります.
$ ls -l $(which passwd)
-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwd*SUIDが設定されているファイル(プログラム)においては所有者の実行権限が s と表記されます. そのため,passwd コマンドは一般ユーザが実行した場合においても,passwd コマンドの所有者である root 権限で実行できます.
SUIDの設定方法
SUIDを設定する場合は,chmod コマンドを用いて
- オクタルモード:
4000を加算 - シンボリックモード:
u+sを付与
## オクタルモードで755に加えて設定したい場合
$ sudo chmod 4755 test.sh
## シンボリックモード
$ sudo chmod u+s test.shSGID
Definition 7 SGID
- ファイルのグループIDが実効グループIDとして設定される仕組みのこと
- GIDではグループの実行権限が
sとなる - ディレクトリに対してSGIDが設定された場合,そのディレクトリ以下において作成したファイルやサブディレクトリの所有グループには,自動的にディレクトリ自体の所有グループが適用される
- 新規作成の場合も,自動的にSGIDのグループが所有グループとなる
SGIDが設定されているディレクトリ例は以下があります
$ find /usr/bin/ -perm -g+s
/usr/bin/chage
/usr/bin/expiry
/usr/bin/crontab
/usr/bin/ssh-agentSGIDの設定方法
SGIDを設定する場合は,chmod コマンドを用いて
- オクタルモード:
2000を加算 - シンボリックモード:
g+sを付与
## オクタルモードで755に加えて設定したい場合
$ sudo chmod 2755 test.sh
## シンボリックモード
$ sudo chmod g+s test.shスティッキービット
Definition 8 スティッキービット
- スティッキービットが設定されたディレクトリ以下のファイルとディレクトリは,実際に設定したアクセス権に関係なく,ファイルのファイル名変更や削除は所有者とrootユーザしかできなくなる
- Permissionではその他グループの実行権限が
tと表示される
/tmp では多くのユーザーが作業できるようにアクセス権がすべて許可されていますが,あるユーザーが作成したファイルを他のユーザーが消してしまうことを防ぐためにスティッキービットが設定されています.
$ ls -ld /tmp
drwxrwxrwt 32 root root 4096 Aug 16 12:46 /tmp/スティッキービットの設定方法
スティッキービットを設定する場合は,chmod コマンドを用いて
- オクタルモード:
1000を加算 - シンボリックモード:
o+tを付与
## オクタルモードで755に加えて設定したい場合
$ sudo chmod 1755 test.sh
## シンボリックモード
$ sudo chmod o+t test.shAppendix: ls -l コマンド
「カーネルが提供する仮想デバイス」の一つである /dev/null を確認してみます
% ls -l /dev/null
crw-rw-rw- 1 root root 1, 3 Jan 13 10:24 /dev/nullls -l の表示
crw-rw-rw- 1 root root 1, 3 Jan 10 12:00 /dev/null
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ ファイル名
│ │ │ │ │ └─ 更新日時
│ │ │ │ └─ サイズ または (major,minor)
│ │ │ └─ グループ
│ │ └─ 所有者
│ └─ ハードリンク数
└─ ファイル種別 + パーミッションファイルの種類
| 文字 | 意味 | file コマンド例 |
実行結果例 |
|---|---|---|---|
- |
普通のファイル | file ~/.ssh/config |
/home/kirby/.ssh/config: ASCII text |
d |
ディレクトリ | file ~/.ssh |
/home/kirby/.ssh/: directory |
l |
シンボリックリンク | file /bin |
/bin: symbolic link to usr/bin |
c |
キャラクタデバイス | file /dev/null |
/dev/null: character special (1/3) |
b |
ブロックデバイス | file /dev/nvme0n1p1 |
/dev/nvme0n1p1: block special (259/1) |
s |
UNIXソケット | file /run/docker.sock |
/run/docker.sock: socket |
p |
名前付きパイプ | file /run/initctl |
/run/initctl: fifo (named pipe) |