1 /* 2 * Copyright (C) 2006 IBM Corporation 3 * 4 * Author: Serge Hallyn <serue@us.ibm.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2 of the 9 * License. 10 * 11 * Jun 2006 - namespaces support 12 * OpenVZ, SWsoft Inc. 13 * Pavel Emelianov <xemul@openvz.org> 14 */ 15 16 #include <linux/slab.h> 17 #include <linux/export.h> 18 #include <linux/nsproxy.h> 19 #include <linux/init_task.h> 20 #include <linux/mnt_namespace.h> 21 #include <linux/utsname.h> 22 #include <linux/pid_namespace.h> 23 #include <net/net_namespace.h> 24 #include <linux/ipc_namespace.h> 25 #include <linux/proc_ns.h> 26 #include <linux/file.h> 27 #include <linux/syscalls.h> 28 #include <linux/cgroup.h> 29 #include <linux/perf_event.h> 30 31 static struct kmem_cache *nsproxy_cachep; 32 33 struct nsproxy init_nsproxy = { 34 .count = ATOMIC_INIT(1), 35 .uts_ns = &init_uts_ns, 36 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC) 37 .ipc_ns = &init_ipc_ns, 38 #endif 39 .mnt_ns = NULL, 40 .pid_ns_for_children = &init_pid_ns, 41 #ifdef CONFIG_NET 42 .net_ns = &init_net, 43 #endif 44 #ifdef CONFIG_CGROUPS 45 .cgroup_ns = &init_cgroup_ns, 46 #endif 47 }; 48 49 static inline struct nsproxy *create_nsproxy(void) 50 { 51 struct nsproxy *nsproxy; 52 53 nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL); 54 if (nsproxy) 55 atomic_set(&nsproxy->count, 1); 56 return nsproxy; 57 } 58 59 /* 60 * Create new nsproxy and all of its the associated namespaces. 61 * Return the newly created nsproxy. Do not attach this to the task, 62 * leave it to the caller to do proper locking and attach it to task. 63 */ 64 static struct nsproxy *create_new_namespaces(unsigned long flags, 65 struct task_struct *tsk, struct user_namespace *user_ns, 66 struct fs_struct *new_fs) 67 { 68 struct nsproxy *new_nsp; 69 int err; 70 71 new_nsp = create_nsproxy(); 72 if (!new_nsp) 73 return ERR_PTR(-ENOMEM); 74 75 new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs); 76 if (IS_ERR(new_nsp->mnt_ns)) { 77 err = PTR_ERR(new_nsp->mnt_ns); 78 goto out_ns; 79 } 80 81 new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns); 82 if (IS_ERR(new_nsp->uts_ns)) { 83 err = PTR_ERR(new_nsp->uts_ns); 84 goto out_uts; 85 } 86 87 new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns); 88 if (IS_ERR(new_nsp->ipc_ns)) { 89 err = PTR_ERR(new_nsp->ipc_ns); 90 goto out_ipc; 91 } 92 93 new_nsp->pid_ns_for_children = 94 copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children); 95 if (IS_ERR(new_nsp->pid_ns_for_children)) { 96 err = PTR_ERR(new_nsp->pid_ns_for_children); 97 goto out_pid; 98 } 99 100 new_nsp->cgroup_ns = copy_cgroup_ns(flags, user_ns, 101 tsk->nsproxy->cgroup_ns); 102 if (IS_ERR(new_nsp->cgroup_ns)) { 103 err = PTR_ERR(new_nsp->cgroup_ns); 104 goto out_cgroup; 105 } 106 107 new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns); 108 if (IS_ERR(new_nsp->net_ns)) { 109 err = PTR_ERR(new_nsp->net_ns); 110 goto out_net; 111 } 112 113 return new_nsp; 114 115 out_net: 116 put_cgroup_ns(new_nsp->cgroup_ns); 117 out_cgroup: 118 if (new_nsp->pid_ns_for_children) 119 put_pid_ns(new_nsp->pid_ns_for_children); 120 out_pid: 121 if (new_nsp->ipc_ns) 122 put_ipc_ns(new_nsp->ipc_ns); 123 out_ipc: 124 if (new_nsp->uts_ns) 125 put_uts_ns(new_nsp->uts_ns); 126 out_uts: 127 if (new_nsp->mnt_ns) 128 put_mnt_ns(new_nsp->mnt_ns); 129 out_ns: 130 kmem_cache_free(nsproxy_cachep, new_nsp); 131 return ERR_PTR(err); 132 } 133 134 /* 135 * called from clone. This now handles copy for nsproxy and all 136 * namespaces therein. 137 */ 138 int copy_namespaces(unsigned long flags, struct task_struct *tsk) 139 { 140 struct nsproxy *old_ns = tsk->nsproxy; 141 struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); 142 struct nsproxy *new_ns; 143 144 if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 145 CLONE_NEWPID | CLONE_NEWNET | 146 CLONE_NEWCGROUP)))) { 147 get_nsproxy(old_ns); 148 return 0; 149 } 150 151 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 152 return -EPERM; 153 154 /* 155 * CLONE_NEWIPC must detach from the undolist: after switching 156 * to a new ipc namespace, the semaphore arrays from the old 157 * namespace are unreachable. In clone parlance, CLONE_SYSVSEM 158 * means share undolist with parent, so we must forbid using 159 * it along with CLONE_NEWIPC. 160 */ 161 if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) == 162 (CLONE_NEWIPC | CLONE_SYSVSEM)) 163 return -EINVAL; 164 165 new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); 166 if (IS_ERR(new_ns)) 167 return PTR_ERR(new_ns); 168 169 tsk->nsproxy = new_ns; 170 return 0; 171 } 172 173 void free_nsproxy(struct nsproxy *ns) 174 { 175 if (ns->mnt_ns) 176 put_mnt_ns(ns->mnt_ns); 177 if (ns->uts_ns) 178 put_uts_ns(ns->uts_ns); 179 if (ns->ipc_ns) 180 put_ipc_ns(ns->ipc_ns); 181 if (ns->pid_ns_for_children) 182 put_pid_ns(ns->pid_ns_for_children); 183 put_cgroup_ns(ns->cgroup_ns); 184 put_net(ns->net_ns); 185 kmem_cache_free(nsproxy_cachep, ns); 186 } 187 188 /* 189 * Called from unshare. Unshare all the namespaces part of nsproxy. 190 * On success, returns the new nsproxy. 191 */ 192 int unshare_nsproxy_namespaces(unsigned long unshare_flags, 193 struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs) 194 { 195 struct user_namespace *user_ns; 196 int err = 0; 197 198 if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 199 CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP))) 200 return 0; 201 202 user_ns = new_cred ? new_cred->user_ns : current_user_ns(); 203 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 204 return -EPERM; 205 206 *new_nsp = create_new_namespaces(unshare_flags, current, user_ns, 207 new_fs ? new_fs : current->fs); 208 if (IS_ERR(*new_nsp)) { 209 err = PTR_ERR(*new_nsp); 210 goto out; 211 } 212 213 out: 214 return err; 215 } 216 217 void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) 218 { 219 struct nsproxy *ns; 220 221 might_sleep(); 222 223 task_lock(p); 224 ns = p->nsproxy; 225 p->nsproxy = new; 226 task_unlock(p); 227 228 if (ns && atomic_dec_and_test(&ns->count)) 229 free_nsproxy(ns); 230 } 231 232 void exit_task_namespaces(struct task_struct *p) 233 { 234 switch_task_namespaces(p, NULL); 235 } 236 237 SYSCALL_DEFINE2(setns, int, fd, int, nstype) 238 { 239 struct task_struct *tsk = current; 240 struct nsproxy *new_nsproxy; 241 struct file *file; 242 struct ns_common *ns; 243 int err; 244 245 file = proc_ns_fget(fd); 246 if (IS_ERR(file)) 247 return PTR_ERR(file); 248 249 err = -EINVAL; 250 ns = get_proc_ns(file_inode(file)); 251 if (nstype && (ns->ops->type != nstype)) 252 goto out; 253 254 new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); 255 if (IS_ERR(new_nsproxy)) { 256 err = PTR_ERR(new_nsproxy); 257 goto out; 258 } 259 260 err = ns->ops->install(new_nsproxy, ns); 261 if (err) { 262 free_nsproxy(new_nsproxy); 263 goto out; 264 } 265 switch_task_namespaces(tsk, new_nsproxy); 266 267 perf_event_namespaces(tsk); 268 out: 269 fput(file); 270 return err; 271 } 272 273 int __init nsproxy_cache_init(void) 274 { 275 nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC); 276 return 0; 277 } 278