user namespace以外のnamespaceはcreate_new_namespaces()で作るけどuser namespaceだけは別ルートになっているのでその辺のめも。 見ているのはLinux 3.16。
user namespaceの場合copy_creds()の処理中に以下のような形で呼ばれる。
339 if (clone_flags & CLONE_NEWUSER) { 340 ret = create_user_ns(new); 341 if (ret < 0) 342 goto error_put; 343 }
copy_creds()が呼び出されるのは下記のような流れです。
clone() -> do_fork() -> copy_process() -> copy_creds()
create_user_ns()はこのような関数ですね。kuid_t、kgit_dに関しては 前に書いた「Linux: コンテナ型の仮想化サポートとkuid_t、kgid_t - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ」参照で。
58 int create_user_ns(struct cred *new) 59 { 60 struct user_namespace *ns, *parent_ns = new->user_ns; 61 kuid_t owner = new->euid; 62 kgid_t group = new->egid; 63 int ret; 64
ここのチェックですがuser namespaceは32段の階層構造までサポートするようです。 他のnamespaceだとこの辺のチェックは無いですね。
65 if (parent_ns->level > 32) 66 return -EUSERS;
次はchrootされているかのチェックで、理由はコメントの通り。
67 68 /* 69 * Verify that we can not violate the policy of which files 70 * may be accessed that is specified by the root directory, 71 * by verifing that the root directory is at the root of the 72 * mount namespace which allows all files to be accessed. 73 */ 74 if (current_chrooted()) 75 return -EPERM; 76
parentのuser namespaceと新規作成するuser namespaceのuid、gidマッピングに関するチェック。
77 /* The creator needs a mapping in the parent user namespace 78 * or else we won't be able to reasonably tell userspace who 79 * created a user_namespace. 80 */ 81 if (!kuid_has_mapping(parent_ns, owner) || 82 !kgid_has_mapping(parent_ns, group)) 83 return -EPERM; 84
見たままですね。
85 ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); 86 if (!ns) 87 return -ENOMEM; 88
procfs経由でuser namespaceを操作できるようにinode番号の確保。
89 ret = proc_alloc_inum(&ns->proc_inum); 90 if (ret) { 91 kmem_cache_free(user_ns_cachep, ns); 92 return ret; 93 } 94
まだ自分以外にこのnamespaceを参照するプロセスはいないのでcountは1に。
95 atomic_set(&ns->count, 1);
ここでuser namespaceを設定。親プロセスのnamespace、自分の階層位置、所有者、グループ。
96 /* Leave the new->user_ns reference with the new user namespace. */ 97 ns->parent = parent_ns; 98 ns->level = parent_ns->level + 1; 99 ns->owner = owner; 100 ns->group = group; 101
set_cred_user_ns()で新規プロセス用のcred構造体(new)に対して今作ったuser namespaceを設定。
102 set_cred_user_ns(new, ns); 103
セマフォの初期化。
104 #ifdef CONFIG_PERSISTENT_KEYRINGS 105 init_rwsem(&ns->persistent_keyring_register_sem); 106 #endif 107 return 0; 108 }
CONFIG_PERSISTENT_KEYRINGSはKconfigのhelpによるとEnable register of persistent per-UID keyringsとのこと。
と、言われてもピンときてないですが。。 まあここは飛ばしても良いか。
ここまででuser namespaceの作成まで終わっているのですがこの機能を実際に使うためにはuid、gidのマッピングが必要になります。この辺は/proc/pid/uid_map、/proc/pid/gid_mapを使います。これについてはLWNのNamespaces in operation, part 5: User namespaces [LWN.net]がサンプルコード付きで解説しているのでそちらをどうぞ。
P.S. user namespaceを使うはカーネルの.configでCONFIG_USER_NS=yになっている必要があります。自分が見たところFedoraはデフォルトのカーネルで有効、Archは無効になってました。
日経Linux(リナックス) 2014年 09月号 [雑誌]
- 作者: 日経Linux編集部
- 出版社/メーカー: 日経BP社
- 発売日: 2014/08/19
- メディア: Kindle版
- この商品を含むブログを見る