1 /* 2 * Copyright (C) 2004 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 12 #include <linux/export.h> 13 #include <linux/uts.h> 14 #include <linux/utsname.h> 15 #include <linux/err.h> 16 #include <linux/slab.h> 17 #include <linux/user_namespace.h> 18 #include <linux/proc_ns.h> 19 20 static struct uts_namespace *create_uts_ns(void) 21 { 22 struct uts_namespace *uts_ns; 23 24 uts_ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 25 if (uts_ns) 26 kref_init(&uts_ns->kref); 27 return uts_ns; 28 } 29 30 /* 31 * Clone a new ns copying an original utsname, setting refcount to 1 32 * @old_ns: namespace to clone 33 * Return ERR_PTR(-ENOMEM) on error (failure to kmalloc), new ns otherwise 34 */ 35 static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, 36 struct uts_namespace *old_ns) 37 { 38 struct uts_namespace *ns; 39 int err; 40 41 ns = create_uts_ns(); 42 if (!ns) 43 return ERR_PTR(-ENOMEM); 44 45 err = proc_alloc_inum(&ns->proc_inum); 46 if (err) { 47 kfree(ns); 48 return ERR_PTR(err); 49 } 50 51 down_read(&uts_sem); 52 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 53 ns->user_ns = get_user_ns(user_ns); 54 up_read(&uts_sem); 55 return ns; 56 } 57 58 /* 59 * Copy task tsk's utsname namespace, or clone it if flags 60 * specifies CLONE_NEWUTS. In latter case, changes to the 61 * utsname of this process won't be seen by parent, and vice 62 * versa. 63 */ 64 struct uts_namespace *copy_utsname(unsigned long flags, 65 struct user_namespace *user_ns, struct uts_namespace *old_ns) 66 { 67 struct uts_namespace *new_ns; 68 69 BUG_ON(!old_ns); 70 get_uts_ns(old_ns); 71 72 if (!(flags & CLONE_NEWUTS)) 73 return old_ns; 74 75 new_ns = clone_uts_ns(user_ns, old_ns); 76 77 put_uts_ns(old_ns); 78 return new_ns; 79 } 80 81 void free_uts_ns(struct kref *kref) 82 { 83 struct uts_namespace *ns; 84 85 ns = container_of(kref, struct uts_namespace, kref); 86 put_user_ns(ns->user_ns); 87 proc_free_inum(ns->proc_inum); 88 kfree(ns); 89 } 90 91 static void *utsns_get(struct task_struct *task) 92 { 93 struct uts_namespace *ns = NULL; 94 struct nsproxy *nsproxy; 95 96 rcu_read_lock(); 97 nsproxy = task_nsproxy(task); 98 if (nsproxy) { 99 ns = nsproxy->uts_ns; 100 get_uts_ns(ns); 101 } 102 rcu_read_unlock(); 103 104 return ns; 105 } 106 107 static void utsns_put(void *ns) 108 { 109 put_uts_ns(ns); 110 } 111 112 static int utsns_install(struct nsproxy *nsproxy, void *new) 113 { 114 struct uts_namespace *ns = new; 115 116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 117 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 118 return -EPERM; 119 120 get_uts_ns(ns); 121 put_uts_ns(nsproxy->uts_ns); 122 nsproxy->uts_ns = ns; 123 return 0; 124 } 125 126 static unsigned int utsns_inum(void *vp) 127 { 128 struct uts_namespace *ns = vp; 129 130 return ns->proc_inum; 131 } 132 133 const struct proc_ns_operations utsns_operations = { 134 .name = "uts", 135 .type = CLONE_NEWUTS, 136 .get = utsns_get, 137 .put = utsns_put, 138 .install = utsns_install, 139 .inum = utsns_inum, 140 }; 141