CAPABILITIES(7) | Linux Programmer's Manual | CAPABILITIES(7) |
名前¶
capabilities - Linux のケーパビリティ (capability) の概要
説明¶
権限のチェックを行う観点から見ると、伝統的な UNIX の実装では プロセスは二つのカテゴリーに分類できる: 特権 プロセス (実効ユーザーID が 0 のプロセス。ユーザーID 0 は スーパーユーザーや root と呼ばれる) と 非特権 プロセス (実効ユーザーID が 0 以外のプロセス) である。 非特権プロセスでは、プロセスの資格情報 (通常は、実効UID 、実効GID と追加のグループリスト) に基づく権限チェックが行われるのに対し、 特権プロセスでは全てのカーネルの権限チェックがバイパスされる。
バージョン 2.2 以降の Linux では、 これまでスーパーユーザーに結び付けられてきた権限を、 いくつかのグループに分割している。これらのグループは ケーパビリティ(capability) と呼ばれ、グループ毎に独立に有効、無効を設定できる。 ケーパビリティはスレッド単位の属性である。
ケーパビリティのリスト¶
以下のリストは、 Linux で実装されているケーパビリティと 各ケーパビリティが許可する操作と動作をまとめたものである。
- CAP_AUDIT_CONTROL (Linux 2.6.11 以降)
- カーネル監査 (audit) の有効無効の切り替え、 監査のフィルタルールの変更、 監査の状況やフィルタルールの取得ができる。
- CAP_AUDIT_READ (Linux 3.16 以降)
- マルチキャスト netlink ソケット経由で監査ログの読み出しができる。
- CAP_AUDIT_WRITE (Linux 2.6.11 以降)
- カーネル監査のログにレコードを書き込む。
- CAP_BLOCK_SUSPEND (Linux 3.5 以降)
- システムのサスペンドをブロックできる機能を使用する (epoll(7) EPOLLWAKEUP, /proc/sys/wake_lock)。
- CAP_CHOWN
- ファイルの UID とGID を任意に変更する (chown(2) 参照)。
- CAP_DAC_OVERRIDE
- ファイルの読み出し、書き込み、実行の権限チェックをバイパスする (DAC は "discretionary access control (任意のアクセス制御)" の略である)。
- CAP_DAC_READ_SEARCH
- ファイルの読み出し権限のチェックとディレクトリの読み出しと実行 の権限チェックをバイパスする。
- open_by_handle_at(2) を起動する。
- 通常、プロセスのファイルシステム 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) 参照)。これには ioctl(2) の KDSIGACCEPT 操作の使用も含まれる。
- CAP_LEASE (Linux 2.4 以降)
- 任意のファイルに対して ファイルリースを設定する (fcntl(2) 参照)。
- CAP_LINUX_IMMUTABLE
- inode フラグ FS_APPEND_FL と FS_IMMUTABLE_FL を設定する (chattr(1) 参照)。
- CAP_MAC_ADMIN (Linux 2.6.25 以降)
- 強制アクセス制御 (MAC) を上書きする。 Smack Linux Security Module (LSM) 用に実装されている。
- CAP_MAC_OVERRIDE (Linux 2.6.25 以降)
- MAC の設定や状態を変更する。 Smack LSM 用に実装されている。
- CAP_MKNOD (Linux 2.4 以降)
- (Linux 2.4 以降) mknod(2) を使用してスペシャルファイルを作成する。
- CAP_NET_ADMIN
- 各種のネットワーク関係の操作を実行する:
- インターフェースの設定
- IP のファイアウォール、マスカレード、アカウンティング
- ルーティングテーブルの変更
- 透過的プロキシでの任意のアドレスの割り当て (bind)
- サービス種別 (type-of-service; TOS) のセット
- ドライバの統計情報のクリア
- promiscuous モードをセットする
- マルチキャストを有効にする
- setsockopt(2) を使って以下のソケットオプションを設定する: SO_DEBUG, SO_MARK, SO_PRIORITY (優先度を 0 から 6 以外に設定する場合), SO_RCVBUFFORCE, and SO_SNDBUFFORCE
- CAP_NET_BIND_SERVICE
- インターネットドメインの特権ポート (ポート番号が 1024 番未満) をバインドできる。
- CAP_NET_BROADCAST
- (未使用) ソケットのブロードキャストと、マルチキャストの待ち受けを行う。
- CAP_NET_RAW
- RAW ソケットと PACKET ソケットを使用する。
- 透過的プロキシでの任意のアドレスの割り当て (bind)
- CAP_SETGID
- プロセスの GID と追加の GID リストに対する任意の操作を行う。 UNIX ドメインソケット経由でソケットの資格情報 (credential) を渡す際に 偽の GID を渡すことができる。 ユーザー名前空間にグループ ID マッピングを書き込むことができる (user_namespaces(7) 参照)。
- CAP_SETFCAP (Linux 2.6.24 以降)
- ファイルケーパビリティを設定する。
- CAP_SETPCAP
- ファイルケーパビリティがサポートされていない場合:
呼び出し元が許可されているケーパビリティセットに含まれる任意のケーパビリティを、
他のプロセスに付与したり、削除したりできる。
(カーネルがファイルケーパビリティをサポートしている場合、
CAP_SETPCAP
はこの役割を持たない。
なぜなら、ファイルケーパビリティをサポートしているカーネルでは
CAP_SETPCAP
は全く別の意味を持つからである。)
ファイルケーパビリティがサポートされている場合: 呼び出し元スレッドのバウンディングセットの任意のケーパビリティを 自身の継承可能ケーパビリティセットに追加できる。 (prctl(2) PR_CAPBSET_DROP を使って) バウンディングセットからケーパビリティを削除できる。 securebits フラグを変更できる。
- CAP_SETUID
- プロセスの UID に対する任意の操作 (setuid(2), setreuid(2), setresuid(2), setfsuid(2)) を行う。 UNIX ドメインソケット経由でソケットの資格情報 (credential) を渡す際に 偽の UID を渡すことができる。 ユーザー名前空間にユーザー ID マッピングを書き込むことができる (user_namespaces(7) 参照)。
- CAP_SYS_ADMIN
- 以下のシステム管理用の操作を実行する: quotactl(2), mount(2), umount(2), swapon(2), swapoff(2), sethostname(2), setdomainname(2).
- 特権が必要な syslog(2) の操作を実行する (Linux 2.6.37 以降では、このような操作を許可するには CAP_SYSLOG を使うべきである)
- VM86_REQUEST_IRQ vm86(2) コマンドを実行する。
- 任意の System V IPC オブジェクトに対する IPC_SET と IPC_RMID 操作を実行する。
- RLIMIT_NPROC リソース制限を上書きする。
- 拡張属性 trusted と security に対する操作を実行する (attr(5) 参照)。
- lookup_dcookie(2) を呼び出す。
- ioprio_set(2) を使って I/O スケジューリングクラス IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE を割り当てる (IOPRIO_CLASS_IDLE は Linux 2.6.25 より前のバージョンのみ)。
- UNIX ドメインソケットでソケットの資格情報 (credential) を渡す際に偽の UID を渡す。
- ファイルをオープンするシステムコール (例えば accept(2), execve(2), open(2), pipe(2)) でシステム全体でオープンできるファイル数の上限 /proc/sys/fs/file-max を超過する。
- clone(2) と unshare(2) で新しい名前空間を作成する CLONE_* フラグを利用する (ただし、 Linux 3.8 以降では、ユーザー名前空間の作成にどのケーパビリティも必要としない)。
- perf_event_open(2) を呼び出す。
- 特権が必要な perf イベントの情報にアクセスする。
- setns(2) を呼び出す (target 名前空間での CAP_SYS_ADMIN が必要)。
- fanotify_init(2) を呼び出す。
- keyctl(2) の KEYCTL_CHOWN と KEYCTL_SETPERM 操作を実行する。
- madvise(2) の MADV_HWPOISON 操作を実行する。
- TIOCSTI ioctl(2) を使って、 呼び出し元の制御端末以外の端末の入力キューに文字を挿入する。
- 廃止予定の nfsservctl(2) システムコールを使用する。
- 廃止予定の bdflush(2) システムコールを使用する。
- 特権が必要なブロックデバイスに対する各種の ioctl(2) 操作を 実行する。
- 特権が必要なファイルシステムに対する各種の ioctl(2) 操作を 実行する。
- 多くのデバイスドライバに対する管理命令を実行する。
- CAP_SYS_BOOT
- reboot(2) と kexec_load(2) を呼び出す。
- CAP_SYS_CHROOT
- chroot(2). を呼び出す。
- CAP_SYS_MODULE
- カーネルモジュールのロード、アンロードを行う (init_module(2) と delete_module(2) を参照のこと)。 バージョン 2.6.25 より前のカーネルで、 システム全体のケーパビリティバウンディングセット (capability bounding set) からケーパビリティを外す。
- CAP_SYS_NICE
- プロセスの nice 値の引き上げ (nice(2), setpriority(2)) や、任意のプロセスの nice 値の変更を行う。
- 呼び出し元プロセスに対するリアルタイムスケジューリングポリシーと、 任意のプロセスに対するスケジューリングポリシーと優先度を設定する (sched_setscheduler(2), sched_setparam(2), shed_setattr(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) を使って任意のプロセスをトレースする。
- get_robust_list(2) を任意のプロセスに対して行う。
- process_vm_readv(2) と process_vm_writev(2) を使って任意のプロセスのメモリーとの間でデータの送受信を行う。
- kcmp(2) を使ってプロセス内部を調査する。
- I/O ポート操作を実行する (iopl(2)、 ioperm(2))。
- /proc/kcore にアクセスする。
- FIBMAP ioctl(2) 操作を使用する。
- x86 モデルに固有のレジスター (MSR レジスター群、 msr(4) 参照) にアクセスするためのデバイスをオープンする。
- /proc/sys/vm/mmap_min_addr を更新する。
- /proc/sys/vm/mmap_min_addr で指定された値よりも小さなアドレスにメモリーマッピングを作成する。
- /proc/bus/pci にあるファイルをマップする。
- /dev/mem や /dev/kmem をオープンする。
- 各種の SCSI デバイスコマンドを実行する。
- hpsa(4) デバイスや cciss(4) デバイスの特定の操作を実行する。
- 他のデバイスに対して各種のデバイス固有命令を実行する。
- ext2 ファイルシステム上の予約されている領域を使用する。
- ext3 のジャーナル機能を制御する ioctl(2) を使用する。
- ディスク quota の上限を上書きする。
- リソース上限を増やす (setrlimit(2))。
- RLIMIT_NPROC リソース制限を上書きする。
- コンソール割り当てにおいてコンソールの最大数を上書きする。
- キーマップの最大数を上書きする。
- リアルタイムクロックから秒間 64 回を越える回数の割り当てが許可する。
- メッセージキューに関する上限 msg_qbytes を /proc/sys/kernel/msgmnb に指定されている上限よりも大きく設定する (msgop(2) と msgctl(2) 参照)。
- F_SETPIPE_SZ fcntl(2) を使ってパイプの容量を設定する際に 上限 /proc/sys/fs/pipe-size-max を上書きする。
- /proc/sys/fs/pipe-max-size に指定されている上限を超えてパイプの容量 を増やすのに F_SETPIPE_SZ を使用する。
- POSIX メッセージキューを作成する際に、 上限 /proc/sys/fs/mqueue/queues_max を上書きする (mq_overview(7) 参照)。
- prctl(2) PR_SET_MM 操作を使用する。
- CAP_SYS_RESOURCE を持ったプロセスによって最後に設定された値よりも小さな値を /proc/PID/oom_score_adj に設定する。
- CAP_SYS_TIME
- システムクロックを変更する (settimeofday(2), stime(2), adjtimex(2))。 リアルタイム (ハードウェア) クロックを変更する。
- CAP_SYS_TTY_CONFIG
- vhangup(2) を使用する。 特権が必要な仮想端末に関する各種の ioctl(2) 操作を利用できる。
- CAP_SYSLOG (Linux 2.6.37 以降)
- CAP_WAKE_ALARM (Linux 3.0 以降)
- システムを起こすトリガーを有効にする (タイマー CLOCK_REALTIME_ALARM や CLOCK_BOOTTIME_ALARM を設定する)。
過去と現在の実装¶
完全な形のケーパビリティを実装するには、以下の要件を満たす必要がある:
- 1.
- 全ての特権操作について、カーネルはそのスレッドの実効ケーパビリティセットに 必要なケーパビリティがあるかを確認する。
- 2.
- カーネルで、あるスレッドのケーパビリティセットを変更したり、 取得したりできるシステムコールが提供される。
- 3.
- ファイルシステムが、実行可能ファイルにケーパビリティを付与でき、ファイル 実行時にそのケーパビリティをプロセスが取得できるような機能をサポートする。
カーネル 2.6.24 より前では、最初の 2つの要件のみが満たされている。 カーネル 2.6.24 以降では、3つの要件すべてが満たされている。
スレッドケーパビリティセット¶
各スレッドは以下の 3種類のケーパビリティセットを持つ。各々のケーパビリティセットは 上記のケーパビリティの組み合わせである (全てのケーパビリティが無効でもよい)。
- 許可 (permitted):
- そのスレッドが持つことになっている実効ケーパビリティの
限定的なスーパーセットである。
これは、実効ケーパビリティセットに
CAP_SETPCAP
ケーパビリティを持っていないスレッドが継承可能ケーパビリティセットに
追加可能なケーパビリティの限定的なスーパーセットでもある。
許可ケーパビリティセットから削除してしまったケーパビリティは、 (set-user-ID-root プログラムか、 そのケーパビリティをファイルケーパビリティで許可しているプログラムを execve(2) しない限りは) もう一度獲得することはできない。
- 継承可能 (inheritable):
- execve(2) を前後で保持されるケーパビリティセットである。 この仕組みを使うことで、あるプロセスが execve(2) を行う際に新しいプログラムの許可ケーパビリティセットとして 割り当てるケーパビリティを指定することができる。
- 実効 (effective):
- カーネルがスレッドの権限 (permission) をチェックするときに 使用するケーパビリティセットである。
fork(2) で作成される子プロセスは、親のケーパビリティセットのコピーを継承する。 execve(2) 中のケーパビリティの扱いについては下記を参照のこと。
capset(2) を使うと、プロセスは自分自身のケーパビリティセット を操作することができる (下記参照)。
Linux 3.2 以降では、 ファイル /proc/sys/kernel/cap_last_cap で、 実行中のカーネルでサポートされているケーパビリティの最大値を参照できる。 この情報を使って、 ケーパビリティセットに設定される可能性がある最上位ビットを判定することができる。
ファイルケーパビリティ¶
カーネル 2.6.24 以降では、 setcap(8) を使って実行ファイルにケーパビリティセットを対応付けることができる。 ファイルケーパビリティセットは security.capability という名前の拡張属性に保存される (setxattr(2) 参照)。この拡張属性への書き込みには CAP_SETFCAP ケーパビリティが必要である。 ファイルケーパビリティセットとスレッドのケーパビリティセットの両方が 考慮され、 execve(2) 後のスレッドのケーパビリティセットが決定される。
3 つのファイルケーパビリティセットが定義されている。
- 許可 (Permitted) (以前の強制 (Forced)):
- スレッドの継承可能ケーパビリティに関わらず、そのスレッドに自動的に 認められるケーパビリティ。
- 継承可能 (Inheritable) (以前の 許容 (Allowed)):
- このセットと、スレッドの継承可能ケーパビリティセットとの 論理積 (AND) がとられ、 execve(2) の後にそのスレッドの許可ケーパビリティセットで有効となる 継承可能ケーパビリティが決定される。
- 実効 (effective):
- これは集合ではなく、1
ビットの情報である。
このビットがセットされていると、
execve(2)
実行中に、そのスレッドの新しい許可ケーパビリティが全て
実効ケーパビリティ集合においてもセットされる。
このビットがセットされていない場合、
execve(2)
後には新しい許可ケーパビリティのどれも新しい実効ケーパビリティ集合
にセットされない。
ファイルの実効ケーパビリティビットを有効にするというのは、 execve(2) 実行時に、ファイルの許可ケーパビリティと継承ケーパビリティに対応するものが スレッドの許可ケーパビリティセットとしてセットされるが、 これが実効ケーパビリティセットにもセットされるということである (ケーパビリティの変換ルールは下記参照)。 したがって、ファイルにケーパビリティを割り当てる際 (setcap(8), cap_set_file(3), cap_set_fd(3))、 いずれかのケーパビリティに対して実効フラグを有効と指定する場合、 許可フラグや継承可能フラグを有効にした他の全てのケーパビリティ についても実効フラグを有効と指定しなければならない。
execve() 中のケーパビリティの変換¶
execve(2)
実行時に、カーネルはプロセスの新しいケーパビリティを次の
アルゴリズムを用いて計算する:
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset) P'(effective) = F(effective) ? P'(permitted) : 0 P'(inheritable) = P(inheritable) [つまり、変更されない]
各変数の意味は以下の通り:
ケーパビリティと、ルートによるプログラムの実行¶
execve(2) 時に、ケーパビリティセットを使って、全ての権限を持った root を実現するには、以下のようにする。
- 1.
- set-user-ID-root プログラムが実行される場合、 またはプロセスの実ユーザー ID が 0 (root) の場合、 ファイルの継承可能セットと許可セットを全て 1 (全てのケーパビリティが有効) に定義する。
- 2.
- set-user-ID-root プログラムが実行される場合、 ファイルの実効ケーパビリティビットを 1 (enabled) に定義する。
上記のルールにケーパビリティ変換を適用した結果をまとめると、 プロセスが set-user-ID-root プログラムを execve(2) する場合、または実効 UID が 0 のプロセスがプログラムを execve(2) する場合、許可と実効のケーパビリティセットの全ケーパビリティ (正確には、ケーパビリティバウンディングセットによるマスクで除外されるもの 以外の全てのケーパビリティ) を取得するということである。 これにより、伝統的な UNIX システムと同じ振る舞いができるようになっている。
ケーパビリティバウンディングセット¶
ケーパビリティバウンディングセット (capability bounding set) は、 execve(2) 時に獲得できるケーパビリティを制限するために使われる セキュリティ機構である。 バウンディングセットは以下のように使用される。
- execve(2) 実行時に、ケーパビリティバウンディングセットと ファイルの許可ケーパビリティセットの論理和 (AND) を取ったものが、 そのスレッドの許可ケーパビリティセットに割り当てられる。 つまり、ケーパビリティバウンディングセットは、 実行ファイルが認めている許可ケーパビリティに対して 制限を課す働きをする。
- (Linux 2.6.25 以降) ケーパビリティバウンディングセットは、スレッドが capset(2) により自身の継承可能セットに追加可能なケーパビリティの母集団を 制限する役割を持つ。 スレッドに許可されたケーパビリティであっても、バウンディングセットに 含まれていなければ、スレッドはそのケーパビリティは自身の継承可能セットに 追加できず、その結果、継承可能セットにそのケーパビリティを含むファイルを execve(2) する場合、そのケーパビリティを許可セットに持ち続けることができない、 ということである。
バウンディングセットがマスクを行うのは、継承可能ケーパビリティではなく、 ファイルの許可ケーパビリティのマスクを行う点に注意すること。 あるスレッドの継承可能セットにそのスレッドのバウンディングセットに 存在しないケーパビリティが含まれている場合、そのスレッドは、 継承可能セットに含まれるケーパビリティを持つファイルを実行することにより、 許可セットに含まれるケーパビリティも獲得できるということである。
カーネルのバージョンにより、ケーパビリティバウンディングセットは システム共通の属性の場合と、プロセス単位の属性の場合がある。
Linux 2.6.25 より前のケーパビリティバウンディングセット
2.6.25 より前のカーネルでは、ケーパビリティバウンディングセットは システム共通の属性で、システム上の全てのスレッドに適用される。 バウンディングセットは /proc/sys/kernel/cap-bound ファイル経由で参照できる。 (間違えやすいが、このビットマスク形式のパラメーターは、 /proc/sys/kernel/cap-bound では符号付きの十進数で表現される。)
init プロセスだけがケーパビリティバウンディングセットで ケーパビリティをセットすることができる。 それ以外では、スーパーユーザー (より正確には、 CAP_SYS_MODULE ケーパビリティを持ったプログラム) が、 ケーパビリティバウンディングセットのケーパビリティのクリアが できるだけである。
通常のシステムでは、ケーパビリティバウンディングセットは、 CAP_SETPCAP が無効になっている。 この制限を取り去るには (取り去るのは危険!)、 include/linux/capability.h 内の CAP_INIT_EFF_SET の定義を修正し、カーネルを再構築する必要がある。
システム共通のケーパビリティバウンディングセット機能は、 カーネル 2.2.11 以降で Linux に追加された。
Linux 2.6.25 以降のケーパビリティバウンディングセット
Linux 2.6.25 以降では、 「ケーパビリティバウンディングセット」はスレッド単位の属性である (システム共通のケーパビリティバウンディングセットはもはや存在しない)。
バウンディングセットは fork(2) 時にはスレッドの親プロセスから継承され、 execve(2) の前後では保持される。
スレッドが CAP_SETPCAP ケーパビリティを持っている場合、そのスレッドは prctl(2) の PR_CAPBSET_DROP 操作を使って自身のケーパビリティバウンディングセットから ケーパビリティを削除することができる。 いったんケーパビリティをバウンディングセットから削除してしまうと、 スレッドはそのケーパビリティを再度セットすることはできない。 prctl(2) の PR_CAPBSET_READ 操作を使うことで、スレッドがあるケーパビリティが自身のバウンディングセット に含まれているかを知ることができる。
バウンディングセットからのケーパビリティの削除がサポートされるのは、 カーネルのコンパイル時にファイルケーパビリティが有効になっている場合 だけである。Linux 2.6.33 より前のカーネルでは、ファイルケーパビリティは 設定オプション CONFIG_SECURITY_FILE_CAPABILITIES で切り替えられる追加の 機能であった。Linux 2.6.33 以降では、この設定オプションは削除され、 ファイルケーパビリティは常にカーネルに組込まれるようになった。 ファイルケーパビリティがカーネルにコンパイル時に組み込まれている場合、 (全てのプロセスの先祖である) init プロセスはバウンディングセットで 全てのケーパビリティが セットされた状態で開始する。ファイルケーパビリティ が有効になっていない場合には、 init はバウンディングセットで CAP_SETPCAP 以外の全てのケーパビリティがセットされた状態で開始する。 このようになっているのは、 CAP_SETPCAP ケーパビリティがファイルケー パビリティがサポートされていない場合には 違った意味を持つからである。
バウンディングセットからケーパビリティを削除しても、 スレッドの継承可能セットからはそのケーパビリティは削除されない。 しかしながら、バウンディングセットからの削除により、 この先そのケーパビリティをスレッドの継承可能セットに追加すること はできなくなる。
ユーザー 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, CAP_LINUX_IMMUTABLE (Linux 2.6.30 以降), CAP_MAC_OVERRIDE, CAP_MKNOD (Linux 2.6.30 以降)。 ファイルシステム UID が 0 以外から 0 に変更された場合、 上記のケーパビリティのうち許可ケーパビリティセットで有効になっているものが 実効ケーパビリティセットで有効にされる。
各種 UID のうち少なくとも一つが 0 であるスレッドが、 その UID の全てが 0 以外になったときに許可ケーパビリティセットが クリアされないようにしたい場合には、 prctl(2) の PR_SET_KEEPCAPS 操作を使えばよい。
プログラムでケーパビリティセットを調整する¶
各スレッドは、 capget(2) や capset(2) を使って、自身のケーパビリティセットを取得したり変更したりできる。 ただし、これを行うには、 libcap パッケージで提供されている cap_get_proc(3) や cap_set_proc(3) を使うのが望ましい。 スレッドのケーパビリティセットの変更には以下のルールが適用される。
- 1.
- 呼び出し側が CAP_SETPCAP ケーパビリティを持っていない場合、新しい継承可能セットは、 既存の継承可能セットと許可セットの積集合 (AND) の部分集合で なければならない。
- 2.
- (Linux 2.6.25 以降) 新しい継承可能セットは、既存の継承可能セットとケーパビリティ バウンディングセットの積集合 (AND) の部分集合でなければならない。
- 3.
- 新しい許可セットは、既存の許可セットの部分集合でなければならない (つまり、そのスレッドが現在持っていない許可ケーパビリティを 獲得することはできない)。
- 4.
- 新しい実効ケーパビリティセットは新しい許可ケーパビリティセットの 部分集合になっていなければならない。
securebits フラグ: ケーパビリティだけの環境を構築する¶
カーネル 2.6.26 以降で、 ファイルケーパビリティが有効になったカーネルでは、 スレッド単位の securebits フラグが実装されており、このフラグを使うと UID 0 (root) に対するケーパビリティの特別扱いを無効することができる。 以下のようなフラグがある。
- SECBIT_KEEP_CAPS
- このフラグをセットされている場合、UID が 0 のスレッドの UID が 0 以外の値に 切り替わる際に、そのスレッドはケーパビリティを維持することができる。 このフラグがセットされていない場合には、UID が 0 から 0 以外の値に 切り替わると、そのスレッドは全てのケーパビリティを失う。 このフラグは execve(2) 時には全てクリアされる (このフラグは、以前の prctl(2) の PR_SET_KEEPCAPS 操作と同じ機能を提供するものである)。
- SECBIT_NO_SETUID_FIXUP
- このフラグをセットすると、スレッドの実効 UID とファイルシステム UID が 0 と 0 以外の間で切り替わった場合に、 カーネルはケーパビリティセットの調整を行わなくなる (「ユーザー ID 変更のケーパビリティへの影響」の節を参照)。
- SECBIT_NOROOT
- このビットがセットされている場合、 set-user-ID-root プログラムの実行時や、 実効 UID か 実 UID が 0 のプロセスが execve(2) を呼び出した時に、カーネルはケーパビリティを許可しない (「ケーパビリティと、ルートによるプログラムの実行」の節を参照)。
上記の "base" フラグの各々には対応する "locked" フラグが存在する。 いずれの "locked" フラグも一度セットされると戻すことはできず、 それ以降は対応する "base" フラグを変更することができなくなる。 "locked" フラグは SECBIT_KEEP_CAPS_LOCKED, SECBIT_NO_SETUID_FIXUP_LOCKED, SECBIT_NOROOT_LOCKED という名前である。
securebits フラグは、 prctl(2) の操作 PR_SET_SECUREBITS や PR_GET_SECUREBITS を使うことで変更したり取得したりできる。 フラグを変更するには CAP_SETPCAP ケーパビリティが必要である。
securebits フラグは子プロセスに継承される。 execve(2) においては、 SECBIT_KEEP_CAPS が常にクリアされる以外は、全てのフラグが保持される。
アプリケーションは、以下の呼び出しを行うことにより、
自分自身および子孫となるプロセス全てに対して、
必要なファイルケーパビリティを持ったプログラムを実行しない限り、
対応するケーパビリティを獲得できないような状況に閉じこめることができる。
prctl(PR_SET_SECUREBITS,
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
ユーザー名前空間との相互作用¶
ケーパリビティとユーザー名前空間の相互の影響に関する議論は user_namespaces(7) を参照。
準拠¶
ケーパビリティに関する標準はないが、 Linux のケーパビリティは廃案になった POSIX.1e 草案に基づいて実装されている。 http://wt.xpilot.org/publications/posix.1e/ を参照。
注意¶
カーネル 2.5.27 以降、ケーパビリティは選択式のカーネルコンポーネント となっており、カーネル設定オプション CONFIG_SECURITY_CAPABILITIES により有効/無効を切り替えることができる。
/proc/PID/task/TID/status ファイルを使うと、スレッドのケーパビリティセットを見ることができる。 /proc/PID/status ファイルには、プロセスのメインスレッドのケーパビリティセットが表示される。 Linux 3.8 より前では、 これらのケーパビリティセットの表示で、 存在しないケーパビリティはすべて有効 (1) として表示される。 Linux 3.8 以降では、 存在しないケーパビリティはすべて無効 (0) として表示される。 (CAP_LAST_CAP より大きい値を持つケーパビリティが存在しないケーパビリティである)。
libcap
パッケージは、ケーパビリティを設定・取得するための
ルーチン群を提供している。これらのインターフェースは、
capset(2) と capget(2)
が提供するインターフェースと比べて、より使いやすく、変更される可能性が少ない。
このパッケージでは、
setcap(8), getcap(8)
というプログラムも提供されている。
パッケージは以下で入手できる。
http://www.kernel.org/pub/linux/libs/security/linux-privs.
バージョン 2.6.24 より前、およびファイルケーパビリティが 有効になっていない2.6.24 以降のカーネルでは、 CAP_SETPCAP ケーパビリティを持ったスレッドは自分以外のスレッドの ケーパビリティを操作できる。 しかしながら、これは理論的に可能というだけである。 以下のいずれかの場合においても、どのスレッドも CAP_SETPCAP ケーパビリティを持つことはないからである。
- 2.6.25 より前の実装では、システム共通のケーパビリティバウンディングセット /proc/sys/kernel/cap-bound ではこのケーパビリティは常に無効になっており、 ソースを変更してカーネルを再コンパイルしない限り、 これを変更することはできない。
- 現在の実装ではファイルケーパビリティが無効になっている場合、 プロセス毎のバウンディングセットからこのケーパビリティを抜いて init は開始され、 システム上で生成される他の全てのプロセスでこのバウンディングセットが 継承される。
関連項目¶
capsh(1), setpriv(2), prctl(2), setfsuid(2), cap_clear(3), cap_copy_ext(3), cap_from_text(3), cap_get_file(3), cap_get_proc(3), cap_init(3), capgetp(3), capsetp(3), libcap(3), credentials(7), user_namespaces(7), pthreads(7), getcap(8), setcap(8)
Linux カーネルソース内の include/linux/capability.h
この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2015-02-01 | Linux |