Provided by: manpages-ja-dev_0.5.0.0.20210215+dfsg-1_all
名前
setns - スレッドに名前空間を関連付けしなおす
書式
#define _GNU_SOURCE /* feature_test_macros(7) 参照 */ #include <sched.h> int setns(int fd, int nstype);
説明
名前空間を参照するファイルディスクリプターを指定すると、 呼び出したスレッドにその名前空間 を関連付けしなおす。 fd 引き数は、 /proc/[pid]/ns/ ディレクトリ内の名前空間エントリー のいずれかを参照するファ イルディスクリプターである。 /proc/[pid]/ns/ の詳細は namespaces(7) を参照。 nstype 引き数 で指定された制限の範囲内で、 呼び出したスレッドに fd に対応する名前空間を関連付けしなお す。 nstype 引き数は、呼び出したスレッドがどのタイプの名前空間を 関連付けしなおすことができるか を指定する。 この引き数には以下のいずれかの値を指定できる。 0 どのタイプの名前空間も関連付けることができる。 CLONE_NEWIPC (Linux 3.0 以降) fd は IPC 名前空間を参照していなければならない。 CLONE_NEWNET (Linux 3.0 以降) fd はネットワーク名前空間を参照していなければならない。 CLONE_NEWNS (Linux 3.8 以降) fd はマウント名前空間を参照していなければならない。 CLONE_NEWPID (Linux 3.8 以降) fd は子孫の PID 名前空間を参照していなければならない。 CLONE_NEWUSER (Linux 3.8 以降) fd はユーザー名前空間を参照していなければならない。 CLONE_NEWUTS (Linux 3.0 以降) fd は UTS 名前空間を参照していなければならない。 呼び出し側が fd がどのタイプの名前空間を参照しているかを知っている (もしくは気にする必要が ない) 場合には、 nstype に 0 を指定すれば十分 である。呼び出し側が fd がどのタイプの名前空 間を参照しているかを 知っておらず、かつ、特定のタイプの名前空間であることを保証したい場 合、 nstype に 0 以外の値を指定するとよい。 (ファイルディスクリプターが別の プロセスにより オープンされ、例えば、UNIX ドメインソケット経由で呼び出し 側に渡された場合などでは、呼び出 し側が fd がどのタイプの名前空間を 参照しているかを知らない可能性がある。) CLONE_NEWPID は他の nstype 値の場合と少し違った動作をする。 呼び出し元スレッドを PID 名前 空間に関連付けし直すと、 呼び出し元の子プロセスが作成される PID 名前空間が変更されるだけで ある。 呼び出し元自身の PID 名前空間は変更されない。 PID 名前空間を関連付けし直すことがで きるのは、 fd で指定された PID 名前空間が呼び出し元の PID 名前空間の子孫 (子プロセス、孫プ ロセスなど) の場合だけである。 PID 名前空間の詳細は pid_namespaces(7) を参照。 プロセスが自分自身をユーザー名前空間に再関連付けするには、 そのプロセスは変更後のユーザー 名前空間において CAP_SYS_ADMIN ケーパビリティを持っていなければならない。 ユーザー名前空間 への参加に成功すると、 そのユーザー ID やグループ ID に関わらず、 プロセスにはその名前空間 におけるすべてのケーパビリティが認められる。 マルチスレッドのプロセスは setns() でユーザー 名前空間を変更できない。 setns() を使って、呼び出し元が現在のユーザー名前空間に再度入るこ とは認められていない。 これにより、 いくつかのケーパビリティを外した呼び出し元が setns() を呼び出すことでそれらのケーパビリティを再度得ることを防ぐことができる。 セキュリティ上の 理由から、 ファイルシステム関連の属性 (共有が clone(2) CLONE_FS フラグで制御される属性) を 別のプロセスと共有している場合、 プロセスは新しいユーザー名前空間に参加できない。 ユーザー 名前空間の詳細は user_namespaces(7) を参照。 プロセスがマルチスレッドの場合、そのプロセスを新しいマウント名前空間に関連付けし直すことは 許可されていない。 マウント名前空間を変更するには、呼び出し元のプロセスが、 自分自身のユー ザー名前空間において CAP_SYS_CHROOT と CAP_SYS_ADMIN の両方のケーパビリティを持っており、 変更後のマウント名前空間で CAP_SYS_ADMIN ケーパビリティを持っていなければならない。 ユー ザー名前空間とマウント名前空間の関係の詳細は user_namespaces(7) を参照。
返り値
成功すると setns() は 0 を返す。 失敗すると、 -1 が返され、 errno にエラーを示す値が設定さ れる。
エラー
EBADF fd が有効なファイルディスクリプターではない。 EINVAL fd が nstype で指定されたタイプと一致しない名前空間を参照している。 EINVAL スレッドを指定された名前空間に関連付けし直す際に問題が発生した。 EINVAL 呼び出し元が先祖 (親や親の親など) の PID 名前空間に参加しようとした。 EINVAL 自分がすでにメンバーとなっているユーザー名前空間に参加しようとした。 EINVAL 呼び出し元が他のプロセスとファイルシステム状態 (特に root ディレクトリ) を共有して いて (CLONE_FS)、 新しいユーザー名前空間に参加しようとした。 EINVAL 呼び出し元プロセスがマルチスレッドで、新しいユーザー名前空間に参加しようとした。 ENOMEM 指定された名前空間に変更するのに必要なメモリーが割り当てられない。 EPERM 呼び出し元スレッドはこの操作を行うのに必要なケーパビリティを持っていなかった。
バージョン
setns() システムコールはカーネル 3.0 で Linux に初めて登場した。 ライブラリによるサポート は glibc バージョン 2.14 を追加された。
準拠
setns() システムコールは Linux 固有である。
注意
新しいスレッドが clone(2) を使って作成された際に共有できる全ての属性を、 setns() を使って 変更できるわけではない。
例
以下のプログラムは 2 つ以上の引き数を取る。 最初の引き数には、 既存の /proc/[pid]/ns/ ディ レクトリの名前空間ファイルのパス名を指定する。 残りの引き数は、コマンドとその引き数を指定 する。 このプログラムは名前空間ファイルをオープンし、 setns() を使って名前空間に参加し、 指定されたコマンドをその名前空間内で実行する。 以下のシェルセッションでは、 このプログラム (ns_exec という名前のバイナリとしてコンパイル されている)を、 clone(2) のマニュアルページの CLONE_NEWUTS のサンプルプログラムと組み合わ せて使っている。 まず、 clone(2) のサンプルプログラムをバックグラウンドで実行する。 このプログラムは、 別の UTS 名前空間で子プロセスを作成する。 子プロセスは自分の名前空間内でホスト名を変更する。 そ れから、 親プロセスと子プロセスの両方でそれぞれの UTS 名前空間のホスト名を表示し、 2 つの ホスト名が違うことが確認できる。 $ su # 名前空間の操作には特権が必要 Password: # ./newuts bizarro & [1] 3549 clone() returned 3550 uts.nodename in child: bizarro uts.nodename in parent: antero # uname -n # シェルでホスト名を確認 antero 次に、以下のプログラムを使ってシェルを実行する。 このシェルの中では、ホスト名が最初のプロ グラムで作成された子プロセスが設定したホスト名になっていることを確認できる。 # ./ns_exec /proc/3550/ns/uts /bin/bash # uname -n # ns_exec で起動されたシェル内で実行 bizarro プログラムのソース #define _GNU_SOURCE #include <fcntl.h> #include <sched.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) int main(int argc, char *argv[]) { int fd; if (argc < 3) { fprintf(stderr, "%s /proc/PID/ns/FILE cmd args...\n", argv[0]); exit(EXIT_FAILURE); } fd = open(argv[1], O_RDONLY); /* 名前空間のディスクリプターを取得 */ if (fd == -1) errExit("open"); if (setns(fd, 0) == -1) /* 名前空間に参加 */ errExit("setns"); execvp(argv[2], &argv[2]); /* 名前空間内でコマンドを実行 */ errExit("execvp"); }
関連項目
clone(2), fork(2), unshare(2), vfork(2), namespaces(7), unix(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。