名前
capabilities - Linux のケーパビリティ (capability) の概要
説明
権限のチェックを行う観点から見ると、伝統的な Unix の実装では プロセスは二つのカテゴリに分類できる: 特権 プロセス (実効ユーザID が 0 のプロセス。ユーザID 0 は スーパーユーザや root と呼ばれる) と 非特権 プロセス (実効ユーザID が 0 以外のプロセス) である。 非特権プロセスでは、プロセスの資格情報 (通常は、実効UID 、実効GID と追加のグループリスト) に基づく権限チェックが行われるのに対し、 特権プロセスでは全てのカーネルの権限チェックがバイパスされる。
バージョン 2.2 以降の Linux では、 これまでスーパーユーザに結び付けられてきた権限を、 いくつかのグループに分割している。これらのグループは ケーパビリティ(capability) と呼ばれ、グループ毎に独立に有効、無効を設定できる。 ケーパビリティはスレッド単位の属性である。
ケーパビリティのリスト
Linux 2.6.14 では、以下のケーパビリティが実装されている:
CAP_AUDIT_CONTROL (Linux 2.6.11 以降) | |
カーネル監査 (audit) の有効無効の切り替え、 監査のフィルタ・ルールの変更、 監査の状況やフィルタ・ルールの取得ができる。 | |
CAP_AUDIT_WRITE (Linux 2.6.11 以降) | |
カーネル監査のログにレコードを書き込むことができる。 | |
CAP_CHOWN | |
ファイルの UID とGID を任意に変更することができる (chown(2) 参照)。 | |
CAP_DAC_OVERRIDE | |
ファイルの読み出し、書き込み、実行の権限チェックがバイパスされる (DAC = "discretionary access control (任意のアクセス制御)")。 | |
CAP_DAC_READ_SEARCH | |
ファイルの読み出し権限のチェックとディレクトリの読み出しと実行 の権限チェックがバイパスされる。 | |
CAP_FOWNER | |
通常、プロセスのファイルシステム UID がファイルの UID に一致することが 要求される操作 (例えば chmod(2), utime(2)) における権限チェックをバイパスする。 但し、 CAP_DAC_OVERRIDE か CAP_DAC_READ_SEARCH によりチェックが行われる操作は除く。 任意のファイルに対して拡張ファイル属性を設定することができる (chattr(1) 参照)。 任意のファイルに対してアクセス制御リスト (ACL) を設定できる。 ファイルの削除の際にディレクトリのスティッキービットを無視する。 open(2) や fcntl(2) で任意のファイルに対して O_NOATIME を指定できる。 | |
CAP_FSETID | |
ファイルが変更されたときにset-user-ID とset-group-ID ビットをクリア しない。呼び出し元プロセスのファイルシステム GID と追加の GID のいずれとも GID が一致しないファイルに対して set-group-ID ビットを設定することができる。 | |
CAP_IPC_LOCK | |
メモリーのロック (mlock(2), mlockall(2), mmap(2), shmctl(2)) を行うことができる。 | |
CAP_IPC_OWNER | |
System V IPC オブジェクトに対する操作に関して権限チェックがバイパスされる。 | |
CAP_KILL | |
シグナルを送信する際に権限チェックがバイパスされる (kill(2) 参照)。 KDSIGACCEPT ioctl の使用も認められる。 | |
CAP_LEASE | |
(Linux 2.4 以降) 任意のファイルに対して ファイルリースを設定することができる (fcntl(2) 参照)。 | |
CAP_LINUX_IMMUTABLE | |
拡張ファイル属性 EXT2_APPEND_FL と EXT2_IMMUTABLE_FL を設定できる (chattr(1) 参照)。 | |
CAP_MKNOD | |
(Linux 2.4 以降) mknod(2) を使用してスペシャル・ファイルを作成することができる。 | |
CAP_NET_ADMIN | |
各種のネットワーク関連の操作を許可する。 (例えば、特権が必要なソケットオプションを設定する、マルチキャストを有効にする、 インターフェースを設定する、ルーティングテーブルを変更するなど) | |
CAP_NET_BIND_SERVICE | |
インターネットドメインで予約されている (1024 番未満の) ソケットポート番号 を使用できる。 | |
CAP_NET_BROADCAST | |
(未使用) ソケットのブロードキャストと、マルチキャストの待ち受けを 行うことができる。 | |
CAP_NET_RAW | |
RAW ソケットと PACKET ソケットを使用することができる。 | |
CAP_SETGID | |
プロセスの GID と追加の GID リストに対する任意の操作を行うことができる。 Unix ドメインソケット経由でソケットの資格情報 (credential) を渡す際に 偽の GID を渡すことができる。 | |
CAP_SETPCAP | |
呼び出し元が許可されているケーパビリティセットに含まれる任意のケーパビリティを、 他のプロセスに付与したり、削除したりできる。 | |
CAP_SETUID | |
プロセスの UID に対する任意の操作 (setuid(2), setreuid(2), setresuid(2), setfsuid(2)) を行うことができる。 Unix ドメインソケット経由でソケットの資格情報 (credential) を渡す際に 偽の UID を渡すことができる。 | |
CAP_SYS_ADMIN | |
以下のシステム管理用の操作を行うことができる: quotactl(2), mount(2), umount(2), swapon(2) , swapoff(2) , sethostname(2), setdomainname(2), 任意の System V IPC オブジェクトに対する IPC_SET と IPC_RMID 操作。 拡張属性 trusted と security に対する操作を実行できる (attr(5) 参照)。 lookup_dcookie(2) を呼び出すことができる。 ioprio_set(2) を使って I/O スケジューリングクラス IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE を割り当てることができる。 keyctl(2) の KEYCTL_CHOWN と KEYCTL_SETPERM 操作を実行できる。 ソケットの資格情報 (credential) を渡す際に偽の UID を渡すことができる。 ファイルをオープンするシステムコール (例えば accept(2), execve(2), open(2), pipe(2)) でシステム全体でオープンできるファイル数の上限 /proc/sys/fs/file-max を超えることができる (このケーパビリティがない場合、この上限に達すると これらのシステムコールは ENFILE エラーで失敗する)。 clone(2) と unshare(2) で CLONE_NEWNS フラグを利用できる。 | |
CAP_SYS_BOOT | |
reboot(2) と kexec_load(2) を呼び出すことができる。 | |
CAP_SYS_CHROOT | |
chroot(2). を呼び出すことができる。 | |
CAP_SYS_MODULE | |
カーネルモジュールのロード、アンロードを行うことができる。 ケーパビリティバウンディングセット (capability bounding set) を変更できる。 (init_module(2) と delete_module(2) を参照のこと) | |
CAP_SYS_NICE | |
プロセスの nice 値の引き上げ (nice(2), setpriority(2)) や、任意のプロセスの nice 値の変更を行うことができる。 呼び出し元プロセスに対するリアルタイム・スケジューリングポリシーの設定と、 任意のプロセスに対するスケジューリングポリシーと優先度の設定を行うことができる (sched_setscheduler(2), sched_setparam(2))。 任意のプロセスに対する CPU affinity を設定できる (sched_setaffinity(2))。 任意のプロセスに対して I/O スケジューリングクラスと優先度を設定できる (ioprio_set(2))。 migrate_pages(2) を任意のプロセスに適用でき、プロセスを任意のノードに移動できる。 move_pages(2) を任意のプロセスに対して行うことができる。 mbind(2) と move_pages(2) で MPOL_MF_MOVE_ALL フラグを使用できる。 | |
CAP_SYS_PACCT | |
acct(2) を呼び出すことができる。 | |
CAP_SYS_PTRACE | |
任意のプロセスに対し ptrace(2) を用いたトレースを行うことができる。 | |
CAP_SYS_RAWIO | |
I/O ポート操作を行うことができる (iopl(2) 、 ioperm(2))。 /proc/kcore にアクセスできる。 | |
CAP_SYS_RESOURCE | |
以下の操作を行うことができる: ext2 ファイルシステム上で予約されている領域の使用。 ext3 のジャーナル機能を制御する ioctl(2) の使用。ディスク quota の上限を上書き。 リソース上限を増やすこと (setrlimit(2))。 RLIMIT_NPROC によるリソース制限の上書き。 メッセージキューに関する上限 msg_qbytes を /proc/sys/kernel/msgmnb に指定されている上限よりも大きく設定すること (msgop(2) と msgctl(2) 参照) | |
CAP_SYS_TIME | |
システムクロックを変更できる (settimeofday(2), stime(2), adjtimex(2))。 リアルタイム (ハードウェア) クロックを変更できる。 | |
CAP_SYS_TTY_CONFIG | |
vhangup(2) を呼び出すことができる。 | |
ケーパビリティセット
各スレッドは以下の 3種類のケーパビリティセットを持つ。各々のケーパビリティセットは 上記のケーパビリティの組み合わせである (全てのケーパビリティが無効でもよい)。
実効 (effective): | |
カーネルがスレッドの権限をチェックするときに使用するケーパビリティ集合。 | |
許可 (permitted): | |
そのスレッドが持つことを許可されているケーパビリティ集合 (言い換えると、 実効ケーパビリティセットと継承可能ケーパビリティセットのスーパーセットである)。 許可ケーパビリティセットから削除してしまったケーパビリティは、 (set-user-ID-root プログラムを execv(2) しない限りは) もう一度獲得することはできない。 | |
継承可能 (inheritable): | |
execve(2) を前後で保持されるケーパビリティ集合。 | |
capset(2) を使うと、プロセスは自分自身のケーパビリティセット を操作することができる。また、 CAP_SETPCAP ケーパビリティを持っている場合には、別プロセスのスレッドの ケーパビリティセットも操作できる。
ケーパビリティバウンディングセット
プログラムが実行されると、、許可ケーパビリティと実効ケーパビリティには、 /proc/sys/kernel/cap-bound で定義されている、 ケーパビリティバウンディングセット (capability bounding set) といわれる値と論理和をとった後の値が設定される。 このパラメータを使うことで、これより後で実行されるすべてのプログラムに 与えられるケーパビリティに対するシステム全体での制限を設けることができる。 (間違えやすいが、ビットマスク形式のパラメータは、 /proc/sys/kernel/cap-bound では符号付きの十進数で表示される。)
init プロセスのみが、ケーパビリティバウンディングセットを設定することが出来る。 また、スーパーユーザーであれば、このセットからビットをクリアする操作 だけは実行できる。
通常のシステムでは、ケーパビリティバウンディングセットは、 CAP_SETPCAP が無効になっている。 この制限を取り去るには (取り去るのは危険!)、 include/linux/capability.h 内の CAP_INIT_EFF_SET の定義を修正し、カーネルを再構築する必要がある。
ケーパビリティバウンディングセット機能の Linux への追加は カーネル 2.2.11 から開始された。
現在と将来の実装
完全な形のケーパビリティを実装するには、以下の要件を満たす必要がある:
1. | 全ての特権操作について、カーネルはそのスレッドの実効ケーパビリティセットに 必要なケーパビリティがあるかを確認する。 |
2. | カーネルで、あるスレッドのケーパビリティセットを変更したり、 取得したりできるシステムコールが提供される。 |
3. | ファイルシステムが、実行可能ファイルにケーパビリティを付与でき、ファイル 実行時にそのケーパビリティをプロセスが取得できるような機能をサポートする。 |
結局、スレッドのケーパビリティセットと連結され、 execve(2) 後のスレッドのケーパビリティセットを決定する 3 つの ケーパビリティセットと、実効可能なファイルとを関係付けることが出来る。
継承可能 (Inheritable) (以前の 許容 (Allowed)): | |
このセットは、スレッドの継承可能ケーパビリティセットと論理和がとられ、 execve(2) の後でスレッドに認められる継承可能ケーパビリティの決定に使われる。 | |
許可 (Permitted) (以前の強制 (Forced)): | |
スレッドの継承可能ケーパビリティに関わらず、そのスレッドに自動的に 認められるケーパビリティ。 | |
実効 (Effective): | |
そのスレッドの新しい許可 (permitted) ケーパビリティセットのうち、 新しい実効ケーパビリティセットでもセットされるケーパビリティ。 (通常、 F(effective) はすべて 0 か、すべて 1 のどちらかとなる) | |
1. | 3種類のファイルケーパビリティセットは初期状態ではクリアされているものと 仮定される。 |
2. | set-user-ID-root プログラムが実行された場合か、プロセスの実ユーザID が 0 (root) の場合は、継承可能と許可のファイルケーパビリティセットが すべて 1 (つまり、全てのケーパビリティが有効) にセットされる。 |
3. | set-user-ID-root プログラムが実行された場合は、実効ファイル ケーパビリティセットが全て 1 にセットされる。 |
exec() 中のケーパビリティの変化
execve(2)
中は、カーネルはプロセスの新しいケーパビリティを次の
アルゴリズムを用いて計算する:
P(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset)
P(effective) = P(permitted) & F(effective)
P(inheritable) = P(inheritable) [つまり、変更されない]
P | execve(2) 前のスレッドのケーパビリティセットの値 |
P | execve(2) 後のスレッドのケーパビリティセットの値 |
F | ファイルケーパビリティセットの値 |
cap_bset | ケーパビリティバウンディングセットの値 |
ユーザ ID 変更のケーパビリティへの影響
ユーザ ID が 0 と 0 以外の間で変化する際の振る舞いを従来と同じにするため、 スレッドの実 UID、実効 UID、保存 set-user-ID、ファイルシステム UID が (setuid(2), setresuid(2) などを使って) 変更された際に、カーネルはそのスレッドのケーパビリティセットに 以下の変更を行う:
1. | UID の変更前には実 UID、実効 UID、保存 set-user-ID のうち 少なくとも一つが 0 で、変更後に実 UID、実効 UID、保存 set-user-ID が すべて 0 以外の値になった場合、許可と実効のケーパビリティセットの 全ケーパビリティをクリアする。 |
2. | 実効 UID が 0 から 0 以外に変更された場合、 実効ケーパビリティセットの全ケーパビリティをクリアする。 |
3. | 実効 UID が 0 以外から 0 に変更された場合、 許可ケーパビリティセットの内容を実効ケーパビリティセットにコピーする。 |
4. | ファイルシステム UID が 0 から 0 以外に変更された場合 (setfsuid(2) 参照)、実効ケーパビリティセットの以下のケーパビリティがクリアされる: CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID. ファイルシステム UID が 0 以外から 0 に変更された場合、 上記のケーパビリティのうち許可ケーパビリティセットで有効になっているものが 実効ケーパビリティセットで有効にされる。 |
準拠
ケーパビリティに関する標準はないが、 Linux のケーパビリティは廃案になった POSIX.1e 草案に基づいて実装されている。
注意
libcap パッケージは、スレッドのケーパビリティを設定・取得するための ルーチン群を提供している。これらのインタフェースは、 capset(2) と capget(2) が提供するインターフェースと比べて、より使いやすく、変更される可能性が少ない。
バグ
今のところ、実行可能ファイルにケーパビリティを結び付ける機能をサポートしている ファイルシステムはない。