Linux パーミッション

# はじめに

## パーミッション

ファイルシステムにおける基本的なセキュリティ機能で、誰が何をできるかを制御する仕組み。

具体的にはファイルやディレクトリに対して読み取り、書き込み、実行といった操作を許可・制限する。

パーミッションはファイルに対するものとディレクトリに対するもので異なる意味を持つ。

| パーミッション | ファイル | ディレクトリ |
|:-:|:-|:-|
| 読み取り（read） | ファイルの中身を表示できる | **ファイル一覧を表示できる** |
| 書き込み（write） | ファイルの中身を編集できる | **ディレクトリ内でファイルを作成・削除できる** |
| 実行（execute）| 実行可能ファイルとして動作させる | **ディレクトリ内にアクセス・移動できる** |

## ファイルの種類

`$ ls -l` コマンド実行で出力される先頭文字は、ファイルの種類を表す。

| 先頭文字 | 意味 |
|:-:|:-|
| `-` | 通常のファイル |
| `d` | ディレクトリ |
| `l` | [シンボリックリンク](https://qiita.com/AsahinaKei/items/8d43c366f061a27ad670#%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%83%E3%82%AF%E3%83%AA%E3%83%B3%E3%82%AF) |
| `c` | [キャラクタデバイス](https://qiita.com/AsahinaKei/items/09ee7ce55b1a0be01ff0#%E3%82%AD%E3%83%A3%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9) |
| `b` | [ブロックデバイス](https://qiita.com/AsahinaKei/items/09ee7ce55b1a0be01ff0#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9) |



# パーミッションを確認する

```console:ファイルのパーミッションを表示する
$ ls -l
```

```console:ディレクトリのパーミッションを表示する
$ ls -ld
```

```console:出力情報の構成
$ ls -l
-rwxr-xr-x 2 root root 4096 Jan 19 06:39 sample.txt

ファイルの種類+権限  リンク数  所有者  所有グループ  ファイルサイズ  タイムスタンプ  ファイル名 
```

権限は以下の通り、所有者、所有グループ、その他のユーザに対して9文字で区別される。

![LPIC (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069520/9e27ac9b-b712-959a-4faf-f666be89ffa3.png)

# パーミッションを変更する

パーミッションを変更することができるのは以下のユーザのみ。

- **ファイルの所有者**
- **`root` ユーザ**

ファイルの「所有グループに所属するユーザ」は、パーミッションを変更することができない。

:::note info
所有グループはパーミッションの変更ができn
:::


## `$ chmod`
change mode

ファイルに付与された権限を変更する。

```console:$ chmod
$ chmod モード ファイル名
```

モードの記述形式には **シンボリック**形式 と **数値**形式 がある。

権限を変更できるのは `root` ユーザと所有者のみ。所有グループに所属するユーザは権限を削除できない。


## シンボリック形式

演算子 `+`、`-`、`=` などを使用して設定を行う方法。

```console:シンボリック形式
$ chmod [対象][演算子][権限] ファイル名
```

| シンボリック形式 | 説明 |
|:-:|:-|
| 対象 | `u`：所有者（user）<br>`g`：グループ（group）<br>`o`：その他ユーザ（other）<br>`a`：**すべてのユーザ**（all） |
| 演算子 | `+` ：追加<br>`-`：削除<br>`=`：設定 |
| 権限 | `r`：読み取り（read）<br>`w`：書き込み（write）<br>`x`：実行（execute）<br>`s`：[SUID](#suid--sgid)、[SGID](#suid--sgid)<br>`t`：[スティッキービット](#スティッキービット) |

```console:（例）所有者に実行権限を追加
$ chmod u+x ファイル名
```

```console:（例）グループの書き込み権限を削除
$ chmod g-w ファイル名
```

```console:（例）その他のユーザに読み取り専用権限を設定
$ chmod o=r ファイル名
```

権限を設定する対象を指定しない場合、 `a` （すべてのユーザ）として扱われる。

```console:（例）すべてのユーザに実行権限を付与
$ chmod +x ファイル名
```

`,` を使うと複数同時に操作ができる。

```console:（例）複数同時に変更
$ chmod u+rwx ファイル名
$ chmod u+r,g-w,o+x ファイル名
```

## 数値形式

数値で設定する場合、所有者、グループ、その他ユーザの権限をそれぞれ数値で表現する。

シンボリック形式とは異なり、設定したい対象が一つでも、三者すべての権限を指定する必要がある。

```console:数値モード
$ chmod [所有者][グループ][その他ユーザ] ファイル名
```

| 権限 | 数値 | ファイル |
|:-:|:-:|:-|
| `r` | `4` | 読み取り（read） |
| `w` | `2` | 書き込み（write） |
| `x` | `1` | 実行（execute）|
| `s` | `4xxx` | [SUID](#suid--sgid) |
| `s` | `2xxx` | [SGID](#suid--sgid) | 
| `t` | `1xxx` | [スティッキービット](#スティッキービット) |

権限は数値の **合計値** で表現する。

```
rwx → 4 (r) + 2 (w) + 1 (x) = 7
rw- → 4 (r) + 2 (w) + 0 (-) = 6
r-- → 4 (r) + 0 (-) + 0 (-) = 4
```

```console:（例）所有者にrwx（7）、グループにrx（5）、その他にrx（5）を設定
$ chmod 755 ファイル名
```

```console:（例）所有者にrw-（6）、グループとその他にr--（4）を設定
$ chmod 644 ファイル名
```

```console:（例）すべての権限を削除（000）
$ chmod 000 ファイル名
```

## SUID / SGID
Set User ID / Set Group ID

実行可能ファイルやディレクトリに設定できる特殊なパーミッション。

`s` で表現される。

```console:SUID を設定する
$ chmod u+s ファイル名
$ chmod u+s ディレクトリ名
```

```console:SGID を設定する
$ chmod g+s ファイル名
$ chmod g+s ディレクトリ名
```

数値は以下のように表現される。

SUID の場合 → 最上位の `4`
SGID の場合 → 最上位の `2`


```console:SUID を数値で設定する
$ chmod 4755 ファイル名
$ chmod 4755 ディレクトリ名
```

```console:SGID を数値で設定する
$ chmod 2755 ファイル名
$ chmod 2755 ディレクトリ名
```

シンボリックリンク、デバイスファイルなどには効果を持たない。
    
### 実行可能ファイルに設定される場合

通常、実行可能ファイルは **実行したユーザの権限** で実行される。

一方、ファイルが SUID 権限を持つ場合 **ファイルを所有するユーザの権限** で実行される。

同様に、実行可能ファイルが SGID 権限を持つ場合 **ファイルを所有するグループの権限** で実行される。

SUID、SGID は主に、システム管理に必要な操作を通常のユーザーが行う際に使用される。

例えば `$ sudo` の実体である `/usr/bin/sudo` ファイルには SUID が設定されている。つまり、一般ユーザが実行した `/usr/bin/sudo` は、ファイルの所有者である `root` が持つ権限において実行される。

```console:sudo コマンドの権限を調べる
$ which sudo
/usr/bin/sudo

$ ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 335120 Jan 19 06:39 /usr/bin/sudo
```

[`$ which`](https://qiita.com/AsahinaKei/items/22d9fae93cabfbf137ee#-which)

他にも、一般ユーザには書き込み権限がない `/etc/passwd` ファイルに保存されたパスワードを変更する `$ passwd` コマンドも SUID 権限で動作している。

```console:/etc/passwd ファイルの権限と passwd コマンドの権限を調べる
$ ls -l /etc/passwd
-rw-r--r-- 1 root root 3010 Jan 19 06:29 /etc/passwd

$ which passwd
/usr/bin/passwd

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 54256 Jan 19 06:39 /usr/bin/passwd
```

ただし、セキュリティ上の理由でスクリプトファイルに設定した SUID、SGID は無視される。

:::note info
スクリプトファイルに設定した SUID、SGID は無視される
:::


### ディレクトリに設定される場合

通常、新規作成されたファイルやディレクトリは、作成者のプライマリグループが所有グループになる。

SGID がディレクトリに設定されている場合、そのディレクトリ内で作成されるファイルやディレクトリは、自動的に親ディレクトリと同じグループが所有するグループとして設定される。

チームで作業する場合、すべてのファイルを同じグループで管理できる。

SUID はディレクトリに対して効果を持たない。

### 理解する

実はプロセスは、内部で複数のユーザ ID を保持している、

| 種類 | 説明 |
|:-|:-|
| 実ユーザID | RUID（**real** UID）<br>プロセスを起動したユーザ ID。 |
| 実効ユーザID | EUID（**effective** UID）<br>実際にどのユーザ権限で動作しているか。<br>SUID なし：RUID と同じ<br>**SUID あり**：**ファイルの所有者** |
| 保存されたユーザID | SUID（saved UID）<br>必要に応じて EUID を切り替えるために保存される。 |
| ファイルシステムユーザID | FSUID（fsuid）<br>ファイルアクセスだけに使われる特別な ID。通常は EUID と同じ。 |

SUID は「ファイルを実行したユーザ（RUID）に関わらず、特定のユーザ権限（EUID）で実行させる」ための仕組みである。

## スティッキービット
sticky=粘着性のある、くっつきやすい

ディレクトリに対して設定することができる、特殊なパーミッション。シンボリック形式で **`t`** で表現される

ファイルの削除権限を、ファイル所有者のみに制限することができる（正確には `root` ユーザも削除可能）。

ファイルの削除権限は、通常、そのファイルが格納されているディレクトリが持つ権限に依存する。

スティッキービットは、[共有ディレクトリ](https://qiita.com/AsahinaKei/items/09ee7ce55b1a0be01ff0#fhs) `/tmp/` のペーミッションとしてよく利用される。`/tmp/` には多くのユーザが一時ファイルを保存するため、各ユーザが他人のファイルを削除できないようにするためである。

```console:/tmp ディレクトリの権限を調べる
$ ls -fd /tmp # 「その他ユーザ」の権限が t になっている
drwxrwxrwt 19 root root 4096 Jan 27 11:13 /tmp 
```

スティッキービットが有効なディレクトリでは、以下のルールが適用される。

- **ファイル所有者だけが、ファイルの削除や名前変更を行える**（加えて `root` ユーザも可能）

- 「その他のユーザ」は、たとえそのディレクトリに書き込み権限があっても、**他人が所有するファイルを削除や変更できない**

```console:シンボリック形式で設定する
$ chmod +t ディレクトリ名
$ chmod o+t ディレクトリ名 # スティッキービットは「その他ユーザ」にのみ影響がある
```

```console:数値形式で設定する
$ chmod 1755 ディレクトリ名
```

この仕組みにより、共有ディレクトリ内での誤操作や悪意ある操作を防ぐことができる。

# `$ umask`

ファイルやディレクトリ作成時に、デフォルトで付与される権限を確認したり、変更することができる。

**`umask` 値** と呼ばれる値を使用する。

```console:デフォルト値を変更する
$ umask umask値
```

`umask` 値は、最大権限から「どの権限を取り除くか」を表わすため、指定した値は「削除する権限」になる。

```
新しい権限 = 最大権限 - umask値
```

`umask` 値が `0` の場合、何も権限を削除しない（最大権限）。

- **最大権限**
  - ファイル：**`666`**（`rw-rw-rw-`）
      - ファイルに対してデフォルトで実行検権限を付与することはできない
  - ディレクトリ：**`777`**（`rwxrwxrwx`）

```console:デフォルト値を確認する
$ umask
0002

# 実際の権限（umask値 - 最大権限 = 実際の権限）
# ファイル      666 - 002 = 664
# ディレクトリ   777 - 002 = 775
```

```console:デフォルト値を文字表現で確認する
$ umask -S
```

# `$ chown`
change owner

ファイルやディレクトリの所有者・所有グループを変更する。実行には `root` 権限が必要。

```console:所有者、所有グループを同時に変更
$ sudo chown ユーザ名:グループ名 ファイル名
```

[`$ sudo`](#-sudo)

所有グループ名の記載は省略できる。

```console:所有者のみ変更
$ sudo chown ユーザ名 ファイル名
```

所有ユーザの記載も省略できる。

```console:所有グループのみ変更
$ sudo chown :グループ名 ファイル名
```

```console:サブディレクトリも含めて再帰的に変更を行う
$ sudo chown -R ユーザ名 ファイル名
```

# `$ chgrp`
change group

ファイルやディレクトリの所有グループを変更する。

一般ユーザで実行した場合、自身の所属グループへの変更しかできない。

```console:ファイルの所有グループを変更
$ sudo chgrp グループ名 ファイル名
```

[`$ sudo`](#-sudo)

# `$ sudo`
super user do

ログイン中のユーザに対して、一時的に管理者（`root`）権限を付与してコマンド実行することができる（仕組みは前述の [SUID](#suid--sgid) を参照）。

```console:$ sudo
$ sudo コマンド
```

管理者しか実行できないコマンド操作でも、`$ sudo` コマンドを使うことによって一般ユーザが実行できるようになる。

```console:現在のシェル環境で実行する
$ sudo -s コマンド
```

```console:指定したユーザ権限で実行する
$ sudo -u ユーザ名 コマンド
```

```console:自身に許可されている root 権限のコマンドを一覧表示する
$ sudo -l
```

※ [`$ visudo`](#-visudo) を参照

# `$ visudo`

**`/etc/sudoers`**（superuser do + er(~する者) + s(複数形)） ファイルを安全に編集するためのエディタ。

`/etc/sudoers` ファイルは `root` 権限の使用を許可するユーザやグループを設定したり、`root` 権限を許可したユーザに対して、どのコマンド実行を許可するかを制御するための設定ファイル。

誤って破壊してしまうと `$ sudo` コマンドが使えなくなる危険があるため、通常の `$ vi` や `$ nano` ではなく `$ visudo` の使用が推奨されている。

```console:/etc/sudoers を編集する専用エディタを起動する
$ sudo visudo
```

**ファイル保存時には自動で構文チェックが行われ、問題がない場合にのみ編集した内容が保存される**。

# `$ su`
switch user

別のユーザーに切り替える。

```console:$ su
$ su ユーザー名
```

`-` を使用した場合、ログイン中のシェルが初期化され、変更先のユーザのホームディレクトリに移動する。（`-` を使用しない場合、ログイン中のシェル環境は変更先のユーザに引き継がれる）

```console:シェル環境の初期化も行う
$ su - ユーザー名
```

ユーザ名を指定しない場合 `root` ユーザに切り替わる。

```console:root に切り替える
$ su -
```

`-c` オプションで、変更先ユーザ権限でコマンド実行ができる。

```console:root 権限でコマンドを実行
$ su -c コマンド root
```

## `$ sudo` と `$ su` の違い

| 違い | `$ sudo` | `$ su` |
|:-:|:-|:-|
| 認証 | 現在のユーザーパスワードを要求 | 切り替え先のユーザーパスワードを要求 |
| 効果 | 実行されるコマンドでのみ権限が昇格 | ログインユーザが完全に切り替わる |