Linux: SUID、SGID、スティッキービットまとめ

## 基本

対象|r|w|x
---|---|---|---
ファイル|読み込み|書き込み|実行
ディレクトリ|ディレクトリ内ファイル一覧の取得（ls）|ディレクトリ内ファイルの作成・削除|ディレクトリに移動（cd）。子孫へのアクセス|

## SUID、SGID、スティッキービットの一覧表
|比較項目          |数値表現|文字列表現|ファイルにつけた場合                               |ディレクトリにつけた場合|実例|
|------------------|--------|----------|---------------------------------------------------|------------------------|----|
|SUID              |4000    |u+s       |そのコマンドが所有者の権限で実行される|意味なし| /usr/bin/su<br>/usr/bin/passwd|
|SGID              |2000    |g+s       |そのコマンドが所有グループの権限で実行される|その中に作成されるファイルやディレクトリはそのグループを継承する| /usr/bin/write|
|スティッキービット|1000    |o+t       |意味なし|その中のファイルを名前変更・削除できるのは所有者のみ | /tmp|

※シェルやPerl等のスクリプトにSUIDを付けても効果がない(無視される）
※本記事はLinuxの場合だが、BSDやSolarisでもまず同じと考えてよい。

## SUIDのついたファイルを探す

```
[/usr/bin:1]# find . -perm +4000 -ls
142970   28 -rwsr-xr-x   1 root     root        27616  3月 13 23:36 ./chfn
153584  116 -rwsr-xr-x   1 root     root       118128  3月 22 09:49 ./sudo
141038   52 -rwsr-xr-x   1 root     root        52192  2月 13 12:59 ./ksu
142811   36 -rwsr-xr-x   1 root     root        33904  3月 15 23:37 ./newuidmap
142806   56 -rwsr-xr-x   1 root     root        55288  3月 15 23:37 ./chage
142944   32 -rwsr-xr-x   1 root     root        31792  3月 13 23:36 ./su
142972   16 -rwsr-xr-x   1 root     root        14872  3月 13 23:36 ./newgrp
142807   24 -rwsr-xr-x   1 root     root        23584  3月 15 23:37 ./expiry
142810   36 -rwsr-xr-x   1 root     root        33904  3月 15 23:37 ./newgidmap
142971   24 -rwsr-xr-x   1 root     root        23432  3月 13 23:36 ./chsh
160521  428 -rwsr-xr-x   1 root     root       434432 11月 12  2014 ./screen-4.2.1
142809   48 -rwsr-xr-x   1 root     root        47224  3月 15 23:37 ./passwd
142951   40 -rwsr-xr-x   1 root     root        40208  3月 13 23:36 ./mount
142808   68 -rwsr-xr-x   1 root     root        68528  3月 15 23:37 ./gpasswd
141480   32 -rwsr-sr-x   1 root     root        31368  6月 16  2014 ./unix_chkpwd
142958   28 -rwsr-xr-x   1 root     root        27664  3月 13 23:36 ./umount
154745   16 -rwsr-xr-x   1 root     root        14696  5月 17 01:47 ./suexec
163465   44 -rwsr-xr-x   1 root     root        44512 11月 25 03:37 ./crontab
142812   40 -rwsr-xr-x   1 root     root        36888  3月 15 23:37 ./sg
```

## SGIDのついたファイルを探す

```
[/usr/bin:1]# find . -perm +2000 -ls
142966   16 -rwxr-sr-x   1 root     tty         14992  3月 13 23:36 ./write
142965   28 -rwxr-sr-x   1 root     tty         27480  3月 13 23:36 ./wall
141480   32 -rwsr-sr-x   1 root     root        31368  6月 16  2014 ./unix_chkpwd
160691   40 -rwxr-sr-x   1 root     locate      39520 12月 15 02:54 ./locate
```

## おまけ：findでパーミッションを指定して検索するオプション

`find . -perm xyz`        ビットが完全に一致するとき
`find . -perm -xyz`       指定ビットの全てが立っているとき（AND）
`find . -perm /xyz`       指定ビットのいずれかが立っているとき（OR）（これが一番よく使うと思う）（従来は `-perm +xyz` だったが2005年にdeperecatedになった）

`find . -perm -111 -ls`と`find . -perm /111 -ls`を比較してみると分かりやすい。

## SUID、SGIDテスト用のコマンド

```printuid.c
// gcc -W -Wall printuid.c -o printuid

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
    uid_t uid = getuid();
    uid_t euid = geteuid();
    gid_t gid = getgid();
    gid_t egid = getegid();

    printf("uid  = %d\n", uid);     // 実際に実行したユーザーのID
    printf("euid = %d\n", euid);    // 実効ユーザーID（SUIDされている場合所有者）
    printf("gid  = %d\n", gid);     // 実際に実行したユーザーのグループ
    printf("egid = %d\n", egid);    // 実効グループID（SGIDされている場合所有グループ）

    return 0;
}
```