Linuxã§åå空éã«é¢ãã¦è¨å®ã§ããã®ã¯clone(2)ãunshare(2)ãsetns(2)ã§ããã®ãã¡å®è¡ä¸ã®ããã»ã¹ã®åå空éãå¤æ´ã§ããã®ã¯å¾è ã®2åãªãã§ãããã«ã¼ãã«å´ã§ã¯kernel/nsproxy.cã«ããswitch_task_namespaces()ãå®éã®å¦çãè¡ã£ã¦ã¾ãããããªããã§ãã®è¾ºãã®ã³ã¼ããè¦ã¦ã¿ã¾ãã
ã¾ããswitch_task_namespaces()ãå¼ãã§ããç®æã§ãã以ä¸ã®4ã¤ãããã¾ãã
- unshareã·ã¹ãã ã³ã¼ã«ã®å®è¡æ
- setnsã·ã¹ãã ã³ã¼ã«ã®å®è¡æ
- exitã·ã¹ãã ã³ã¼ã«å®è¡æ
- copy_process()ã®ã¨ã©ã¼å¦ç
ãã®ãã¡1ã2ã¯å®è¡ä¸ã®ããã»ã¹ã®åå空éãåãæ¿ããããã3ã¯ããã»ã¹ã®çµäºå¦çã®ä¸ç°ã§ä½¿ç¨ãã¦ããåå空éãããã»ã¹ããåç §ã§ããªãããããããæå¾ã¯åå空éãè¨å®ãããã©ããã»ã¹ã®çæã«å¤±æããã®ã§å¾å§æ«ã¨ããã¨ããã§ãã
unshare(2)ã®å ´åã¯unshare()ã§ãã®ããã«å¼ã³åºãã¦ãã¾ãã
1864 err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, 1865 ãç¥ã 1877 if (new_nsproxy) 1878 switch_task_namespaces(current, new_nsproxy); 1879
setns(2)ã®å ´åã¯setns()ã§ãã®ããã«ãtskã¯currentã§ãã
247 new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); ãç¥ã 258 switch_task_namespaces(tsk, new_nsproxy);
ãã¦ãswitch_task_namespaces()ã§ããããã¯å ¨é¨ã§20è¡ã»ã©ã®é¢æ°ã§ããmight_sleep()ã¯ãããã°æ©è½ã®CONFIG_DEBUG_ATOMIC_SLEEPãyã«ãªã£ã¦ããªããã°ä½ãããªãã®ã§ã³ã³ãã¤ã«æã®æé©åã§æ¶ããã¦ããã¯ãã§ãã
201 void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) 202 { 203 struct nsproxy *ns; 204 205 might_sleep(); 206 207 ns = p->nsproxy; 208 209 rcu_assign_pointer(p->nsproxy, new); 210 211 if (ns && atomic_dec_and_test(&ns->count)) { 212 /* 213 * wait for others to get what they want from this nsproxy. 214 * 215 * cannot release this nsproxy via the call_rcu() since 216 * put_mnt_ns() will want to sleep 217 */ 218 synchronize_rcu(); 219 free_nsproxy(ns); 220 } 221 } 222
ãã®é¢æ°ã®å
容ã¯rcu_assign_pointer()ã§ç¾å¨è¨å®ããã¦ããåå空éã®ã¸ã®ãã¤ã³ã¿ã¸newãã»ãããããã¦ã使ç¨ãã¦ããåå空éãNULLã§ãªãããªãã¡ã¬ã³ã¹ã«ã¦ã³ã¿ããã¯ãªã¡ã³ãããçµæcountã0ã«ãªã£ãå ´åãåå空éãè¨å®ããã¦ãã¦ãã¤ãã®ããã»ã¹ã®åå空éï¼p->nsproxyï¼ã誰ã使ã£ã¦ããªããå ´åã«åå空éã解æ¾ãã¦ãã¾ãã
free_nsproxy()ã¯ç¹ã«é¢ç½ããã¨ã¯ãã£ã¦ããªãã¦ãååå空éï¼utsãmountçï¼ã®åç
§ã«ã¦ã³ã¿ãæ¸ãããæå¾ã«nsproxyæ§é ä½ã®ã¤ã³ã¹ã¿ã³ã¹ãkmem_cache_free()ã§è§£æ¾ããã ãã§ãã
unshare()ãsetns()ã®å ´åãswitch_task_namespaces()ã®å¼ã³åºãåã«ã¯æ°ããä½ã£ãstruct nsproxyã渡ãã¦ãã¾ããsetns()ã§ä½¿ã£ã¦ããcreate_new_namespaces()ã«é¢ãã¦ã¯create_new_namespaces()ããã§è»½ãã¾ã¨ãã¦ãã¾ãã
unshare_nsproxy_namespaces()ã¯ã¨ããã¨ããã¡ãããããªã«å¤§ãããã¨ã¯ãã£ã¦ããªãã®ã§è»½ãè¦ã¦ãã¾ãã¾ãã
176 int unshare_nsproxy_namespaces(unsigned long unshare_flags, 177 struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs) 178 { 179 struct user_namespace *user_ns; 180 int err = 0; 181 182 if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 183 CLONE_NEWNET | CLONE_NEWPID))) 184 return 0; 185 186 user_ns = new_cred ? new_cred->user_ns : current_user_ns(); 187 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 188 return -EPERM; 189 190 *new_nsp = create_new_namespaces(unshare_flags, current, user_ns, 191 new_fs ? new_fs : current->fs); 192 if (IS_ERR(*new_nsp)) { 193 err = PTR_ERR(*new_nsp); 194 goto out; 195 } 196 197 out: 198 return err; 199 }
æåã«ååå空éã®ãã©ã°ããã§ãã¯ãã¦1ã¤ãè¨å®ããã¦ããªããã°0ãè¿ãã¦é¢æ°ãæãã¾ããããã®å ´åã¯new_nspãè¨å®ãããªãã®ã§unshare()å ã®ä»¥ä¸ã®ifæã®ãã§ãã¯ã«å¼ã£ããã£ã¦switch_task_namespaces()ã¯å¼ã°ãã¾ããã
1877 if (new_nsproxy) 1878 switch_task_namespaces(current, new_nsproxy);
ãã®å¾ãã±ã¼ãããªãã£ã®ãã§ãã¯ããã¦åé¡ãªããã°create_new_namespaces()ã§æ°ããåå空éã®ã¤ã³ã¹ã¿ã³ã¹ãä½æã¨ããæµãã§ãã
Linuxããã°ã©ãã³ã°ã¤ã³ã¿ãã§ã¼ã¹
- ä½è : Michael Kerrisk,åä½æ²»é
- åºç社/ã¡ã¼ã«ã¼: ãªã©ã¤ãªã¼ã¸ã£ãã³
- çºå£²æ¥: 2012/12/01
- ã¡ãã£ã¢: 大åæ¬
- ã¯ãªãã¯: 14å
- ãã®ååãå«ãããã° (5件) ãè¦ã