Other Alias
capset書式
#include <sys/capability.h>int capget(cap_user_header_t hdrp, cap_user_data_t datap);
int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
説明
Linux 2.2 で、スーパーユーザー (root) の権限は、個別のケーパビリティ (capabilities) へと分割され、その集合として表現されるようになった。 各スレッドは「実効ケーパビリティ (effective capability) の集合」を持ち、 それによって現在どの操作が実行可能かを識別できる。 また、各スレッドは、 「継承可能ケーパビリティ (inheritable capability) の集合」と 「許可ケーパビリティ (permitted capability) の集合」を持つ。 「継承可能ケーパビリティの集合」は execve(2) を通じて渡すことができるケーパビリティの集合であり、 「許可ケーパビリティ (permitted capability) の集合」は 実効ケーパビリティや継承可能ケーパビリティとして有効にできる ケーパビリティを規定するものである。この二つのシステムコールはスレッドのケーパビリティを取得したり設定したりするための 生のカーネルインターフェースである。 これらのシステムコールは Linux 特有であるというだけでなく、 カーネル API は変更されるかもしれず、これらのシステムコールの使用法 (特に cap_user_*_t 型という書式) はカーネルのリビジョン毎に拡張されるかもしれないが、 以前のプログラムはそのまま動作する。
移植性のあるインターフェースは cap_set_proc(3) と cap_get_proc(3) である。 可能ならばアプリケーションはこれらの関数を使用すべきである。 アプリケーションに Linux 拡張を使用したい場合には、より簡単に 使えるインターフェースである capsetp(3) と capgetp(3) を使用すべきである。
現在の詳細
現在のカーネルの詳細について注意を述べておく。 構造体は以下のように定義される。
#define _LINUX_CAPABILITY_VERSION_1 0x19980330 #define _LINUX_CAPABILITY_U32S_1 1 #define _LINUX_CAPABILITY_VERSION_2 0x20071026 #define _LINUX_CAPABILITY_U32S_2 2 typedef struct __user_cap_header_struct { __u32 version; int pid; } *cap_user_header_t; typedef struct __user_cap_data_struct { __u32 effective; __u32 permitted; __u32 inheritable; } *cap_user_data_t;
フィールド effective, permitted, inheritable は、 capabilities(7) で定義されるケーパビリティのビットマスクである。 CAP_* はビット番号を表すインデックス値であり、 ビットフィールドに OR を行う前に CAP_* の値の分だけビットシフトを行う必要がある。 typedef の方はポインタなので、 このシステムコールに渡す構造体を定義するには、 struct __user_cap_header_struct と struct __user_cap_data_struct という名前を使用しなければならない。
カーネル 2.6.25 より前では、バージョン _LINUX_CAPABILITY_VERSION_1 の 32 ビットケーパビリティが推奨である。 カーネル 2.6.25 以降では、バージョン _LINUX_CAPABILITY_VERSION_2 の 64 ビットケーパビリティが推奨である。 64 ビットケーパビリティでは datap[0] と datap[1] が使用されるのに対し、 32 ビットケーパビリティでは datap[0] だけが使用される。
これらのシステムコールの挙動に影響があるもう一つの変更点は、 ファイルケーパビリティ (file capabilities) のカーネルによるサポート (VFS ケーパビリティのサポート) である。 VFS ケーパビリティのサポートは現在のところコンパイル時のオプションである (カーネル 2.6.24 で追加された)。
capget() では、 hdrp->pid のフィールド値にケーパビリティを知りたいプロセスのプロセス ID を 指定することで、任意のプロセスのケーパビリティを調べることができる。
VFS ケーパビリティがサポートされている場合
VFS ケーパビリティのサポートでは、特権実行ファイルにケーパビリティを 追加するためのファイル属性メソッドが作成された。 この特権モデルの導入により、あるプロセスにより別のプロセスのケーパビリティ を非同期に設定する機能のカーネルによるサポートは廃止される。 つまり、VFS サポートでは、 capset() を呼び出す際に hdrp->pid の値として許されるのは 0 と getpid(2) が返す値だけとなる (どちらの値でも等価である)。VFS ケーパビリティがサポートされていない場合
カーネルが VFS ケーパビリティをサポートしていない場合、 hdrp の pid フィールドが 0 以外であれば、 capset() の操作対象は pid で指定されたスレッドのケーパビリティになる。 pid が 0 の場合は呼び出し元のスレッドのケーパビリティが操作対象となる。 pid がシングルスレッド・プロセスを参照している場合、 pid は以前から使われているプロセスID を使って指定できる。 マルチスレッド・プロセス内のあるスレッドを対象にする場合は、 gettid(2) が返すスレッドID を用いて指定する必要がある。 また、 capset() では -1 や -1 より小さな値を指定することもできる。 -1 は呼び出し元と init(8) を除く全てのスレッドを対象として変更を行うことを、 -1 より小さな値は ID が -pid のプロセスグループの全メンバ を対象として変更を行うことを意味する。このデータの詳細は capabilities(7) を参照すること。
返り値
成功した場合は 0 が返される。エラーの場合は -1 が返され、 errno が適切に設定される。hdrp のフィールド version にサポートされていない値が指定された場合、 呼び出しはエラー EINVAL で失敗し、 version にカーネル推奨の _LINUX_CAPABILITY_VERSION_? を設定する。 このようにして、現在の推奨ケーパビリティ・リビジョンが何かを 調べることができる。
エラー
- EFAULT
- 不正なメモリアドレス。 hdrp は NULL であってはならない。 datap に NULL を指定してよいのは、ユーザがカーネルがサポートしている 推奨のケーパビリティ・バージョンを判定しようとしているときだけである。
- EINVAL
- 引き数のどれかが無効である。
- EPERM
- 「許可ケーパビリティセット」にケーパビリティを追加しようとしているか、 もしくは「許可ケーパビリティセット」に含まれないケーパビリティを 「実効ケーパビリティセット」や「継承可能ケーパビリティセット」に セットしようとしている。
- EPERM
- 呼び出し元が自分以外のスレッドのケーパビリティを capset() を使って修正しようとしたが、十分な特権がなかった。 VFS ケーパビリティをサポートしているカーネルでは、 この操作が許可されることは決してない。 VFS ケーパビリティをサポートしていないカーネルでは、 CAP_SETPCAP ケーパビリティが必要である。 (バージョン 2.6.11 より前のカーネルには、 このケーパビリティを持たないスレッドが pid フィールドに 0 でない値 (つまり、0 の代わりに getpid(2) が返す値) を指定して自分自身のケーパビリティを変更しようとした場合にも、 このエラーが発生するというバグがあった。)
- ESRCH
- そのようなスレッドが存在しない。
準拠
これらのシステムコールは Linux 独自である。注意
ケーパビリティを設定したり取得したりする機能のための移植性ある インターフェースは libcap ライブラリによって提供される。 このライブラリは以下から入手できる:この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。