誰得なめも。task_structからuser_nsの取得の方法。
名前空間はstruct nsproxyで管理されているけど、user namespaceはstruct credが管理していて、user namespace以外の名前空間はその構造体にuser namespaceへのポインタを持っている。 このポインタがどう使われるかというと、流れとしては、do_fork()からcopy_namespace()を呼び、そこからcreate_new_namespaces()を呼ぶときに、user namespaceを引数として渡して、get_user_ns()で参照カウントを増やす。
例えば、clone_uts_ns()でuts namespaceを新規に作成した時に、新しく作ったuts名前空間のuser_nsは引数で渡されたuser namespaceを参照するようにしている。
54 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 55 ns->user_ns = get_user_ns(user_ns); 56 up_read(&uts_sem);
では、実際の処理を。 struct task_structはstruct credを2個持っていて、どちらをcopy_namespace()に渡しているのか?ってなるので、そこから見ます。
1440 /* process credentials */ 1441 const struct cred __rcu *real_cred; /* objective and real subjective task 1442 * credentials (COW) */ 1443 const struct cred __rcu *cred; /* effective (overridable) subjective task 1444 * credentials (COW) */ 1445 char comm[TASK_COMM_LEN]; /* executable name excluding path 1446 - access with [gs]et_task_comm (which lock 1447 it with task_lock()) 1448 - initialized normally by setup_new_exec */ 1449 /* file system info */
copy_namespaces()では、下記のようにtask_structからuser namespaceを取得している。
127 struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
task_cred_xxx()はマクロでこのような処理。これを見ると実際にuser namespaceを返すのは328行目の__task_cred((task))->xxx
というのがわかりますね。
324 #define task_cred_xxx(task, xxx) \ 325 ({ \ 326 __typeof__(((struct cred *)NULL)->xxx) ___val; \ 327 rcu_read_lock(); \ 328 ___val = __task_cred((task))->xxx; \ 329 rcu_read_unlock(); \ 330 ___val; \ 331 })
で、 __task_cred()はというと、このようなマクロです。task_structにあった2個のstruct credのうち、real_credの方を使ってますね。
281 #define __task_cred(task) \ 282 rcu_dereference((task)->real_cred)
というわけで、user namespace以外のnamespacesはtask_structのメンバ変数real_credを参照するとわかりました。
Dockerエキスパート養成読本[活用の基礎と実践ノウハウ満載!] (Software Design plus)
- 作者: 杉山貴章,大瀧隆太,Yugui(Yuki Sonoda),中津川篤司,前佛雅人,松原豊,松本勇気
- 出版社/メーカー: 技術評論社
- 発売日: 2015/06/18
- メディア: 大型本
- この商品を含むブログ (1件) を見る